[+] Filter post title options for the Connect Existing select2.js field in the post relationships panel of the post editor screen

In the post editor screen, a post relationships panel can be used to “Connect Existing” posts in a post relationship. Users must select from existing post titles using a select2.js custom select field. If you have several possible posts with similar names, it might not be obvious which post you should select. You might want to add some additional identifying information, like a custom field value or a related post title from another post relationship. You can use the posts_results hook to filter those post titles. The following code snippet shows how you might accomplish this.

/* --------------------------------------------------------
 * FILTER POST TITLES IN CONNECT EXISTING SELECT2.JS FIELD 
 * IN POST RELATIONSHIPS PANEL IN POST EDITOR SCREEN
 * Use posts_results hook to customize the post titles shown as options in the select2.js field 
 * displayed when using the Connect Existing feature in post relationships panel of post editor screen
 * @$posts: array of post objects to be displayed in select2.js field
 * @$query: query that was used to fetch $posts results
 */
function ts_filter_connect_existing_titles( $posts, $query ){
  $post_types = ['band', 'event'];  // edit the slug(s) of post type(s) to modify
  $rel_slugs = ['band-event'];      // edit the slug(s) of post relationship(s) where you want to modify titles

  // !! - You probably should not edit anything in these conditionals. skip to the foreach code to manipulate titles - !!
  
  // We only want to run this if User is searching for related content for specific relationships using the Connect Existing dialog
  if ( defined('DOING_AJAX')
   && isset($_REQUEST['action'])
   && $_REQUEST['action']=='types_related_content_action'
   && isset($_REQUEST['relationship_slug'])
   && in_array($_REQUEST['relationship_slug'], $rel_slugs)
   && isset($query->query['post_type'][0])
   && in_array($query->query['post_type'][0], $post_types)
  ) {
    foreach($posts as $post){

      // this loops over each WP Post object that will be included in select2.js options
      // modify the titles of each post here as desired
      $post->post_title = 'Test-' . $post->post_title;

    }
  }
  return $posts;
}
add_action( 'posts_results', 'ts_filter_connect_existing_titles', 99, 2 );

You can adjust the post type slugs band and event, as well as the post relationship slug band-event to match your content. This code will manipulate the titles of posts in any of the post types included in the $post_types array, in the Connect Existing dialog available for any of the post relationships included in the $rel_slugs array. Modify the post titles however you’d like in the foreach loop. Note that this does not extend search capabilities – i.e. you cannot search for the modified title. The modification only applies to the title displayed in the select2.js field options.

[+] Display Next and Previous links to paginate between sibling posts in a one-to-many relationship

In this example, we have created a custom shortcode you can use to display pagination links like “Next: Next Sibling Post Title” and “Previous: Previous Sibling Post Title” to navigate among sibling child posts in a one-to-many post relationship. You can place this shortcode in the child post template to generate the appropriate link programmatically and display it only if necessary.

// get a link to the next or previous sibling post in child post content template
// example: [tssupp-next-prev-child current="[wpv-post-id]" step="1" relslug="book-chapter"][/tssupp-next-prev-child]
// @current: current post id
// @step: 1 for next or -1 for previous
// @relslug: slug of the post relationship
  
function tssupp_next_prev_child($atts) {
  $a = shortcode_atts( array(
    'current' => 0,
    'step' => '1',
    'relslug' => '',
  ), $atts );
  $link = '';
  
  // get all child posts
  $relationship_slug = $a['relslug'];
  $current_child_id = $a['current'];
  $parent_id = toolset_get_related_post( $current_child_id, $relationship_slug );
  $sibling_args = array(
    'query_by_role'=>'parent',
    'limit'=>1000,
    'role_to_return'=>'child',
    'orderby'=>'title'
  );
  $siblings = toolset_get_related_posts( $parent_id, $relationship_slug, $sibling_args );
  
  // loop over child posts and get index of the current post
  foreach($siblings as $i=>$sibling) {
    if( $sibling == $current_child_id ) {
      break;
    }
  }
  
  // increment or decrement index for next or previous sibling
  $i += $a['step'];
  
  // create link to next/previous sibling
  if(isset($siblings[$i])){
    $perm = get_the_permalink( $siblings[$i] );
    $title = get_the_title( $siblings[$i] );
    $link .= $a['step']=='1' ? "Next: " : "Previous: ";
    $link .= "<a href='" . $perm . "'>" . $title . "</a>";
  }
  
  // output the link, or empty string if not set
  return $link;
}
add_shortcode( 'tssupp-next-prev-child', 'tssupp_next_prev_child' );

Use the shortcode like this to generate a “Next” link (if necessary):

[tssupp-next-prev-child step="1" relslug="book-chapter" current="[wpv-post-id]"][/tssupp-next-prev-child]

Replace book-chapter with the slug of the post relationship.

You’ll change the step value to -1 to generate a “Previous” link (if necessary):

[tssupp-next-prev-child step="-1" relslug="book-chapter" current="[wpv-post-id]"][/tssupp-next-prev-child]

Again, replace book-chapter with the slug of the post relationship.

If you want to modify the links, you should only need to edit this part of the code:

// create link to next/previous sibling
  if(isset($siblings[$i])){
    $perm = get_the_permalink( $siblings[$i] );
    $title = get_the_title( $siblings[$i] );
    $link .= $a['step']=='1' ? "Next: " : "Previous: ";
    $link .= "<a href='" . $perm . "'>" . $title . "</a>";
  }

Redirect to parent post after editing Repeatable Field Group (RFG) in Forms

In this example, we have a repeatable field group (RFG) assigned to some custom post type. On the single post page, we are showing a View of the RFG related to the current post. We want to give some Users the ability to edit those RFGs on the front-end using Forms. In the current system, the recommended approach is to use an Edit Post link in the View to send the User to a page containing a Form. This can be a tedious workflow if you must edit multiple RFGs, going back and forth from the parent post to the Form editor. This code snippet can be used to automatically redirect the User to the post containing the RFG, saving one step in the process. Note that you must set the Form to redirect to some existing Page in the Form configurations. Otherwise, the redirect code will not have any effect on the Form.

/* ----------------------------------------------------------------------- */
// REDIRECT TO RFG PARENT POST AFTER EDITING RFG IN FORMS
// After submitting edit RFG Form, redirect to the post containing the RFG
// Be sure to set some redirect in wp-admin for this Form
//
add_filter('cred_success_redirect', 'custom_redirect_rfg_editor',10,3);
function custom_redirect_rfg_editor($url, $post_id, $form_data)
{
  $forms = array( 12345 );
  $rfg_slug = 'your-rfg-slug';
  if ( in_array( $form_data['id'], $forms ) ) {
    $parent_id = toolset_get_related_post( $post_id, $rfg_slug );
    return get_permalink($parent_id);
  }
  return $url;
}

Filter a View of child posts by parent post status, where the parent is not private

In this example, we have a one-to-many post-relationship between two custom post types, and we want to set up a View of child posts. Since some parent posts are private, we do not want to show their children. Set up a View of child posts with no post-relationship filter. Then use this code snippet to filter out all private parents’ children from the results.

/* --------------------------------------------------------------------------------- */
// FILTER A VIEW OF CHILD POSTS BY PARENT POST STATUS NOT EQUAL TO PRIVATE
// This filter can be applied to any View of child posts to filter out
// children of private parent posts.
// ---------------------------------------------------------------------------------
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( 12345 ); // 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' => 'child-type-slug',
      '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, 'relationship-slug', '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;
}

Replace 12345 with the numeric ID of your View of child posts, or a comma-separated list of numeric View IDs if you want to apply this filter to more than one View. Replace child-type-slug with the slug of the child post type, and replace ‘relationship-slug’ with the slug of the post-relationship. Consider adding more criteria to the child post query to improve the performance of this filter if a large number of child posts exist.