• I know that I’m going against the grain here a bit, but I’ve got a blog where I author several (5-15) posts for a couple week long camping adventure, and I often want to link between those posts before I actually publish them.

    Of course, I want the links to continue to work after publishing, and I never change the titles once I’m done writing – they just sit in draft state until I publish.

    I was hoping that I could hook the post_link filter so that I could use the “insert hyperlink search” functionality in TinyMCE at author time – the UI where you click the insert link button, and start typing search terms to bring up the relevant posts/pages, and choose one that you want to link to.

    The code I’ve got to do this in my functions.php is as follows:

    
    function draft_permalink( $post) {
        if (in_array($post->post_status, array('draft', 'pending', 'auto-draft'))) {
            $my_post = clone $post;
            $my_post->post_status = 'published';
            $my_post->post_name = sanitize_title($my_post->post_name ? $my_post->post_name : $my_post->post_title, $my_post->ID);
            $permalink = get_permalink($my_post);
        } else {
            $permalink = get_permalink();
        }
    
        return $permalink;
    }
    
    function get_draft_permalink( $url, $post, $leavename=false ) {
    
    	if ( $post->post_status == 'draft' )
    		$url = draft_permalink($post);
    
    	return $url;
    }
    add_filter( 'post_link', 'get_draft_permalink', 10, 3 );
    

    However, I’m not seeing any of my draft posts show up in the list when I type terms in their names.

    Am I missing something simple?

    Thanks!

Viewing 7 replies - 1 through 7 (of 7 total)
  • Moderator bcworkz

    (@bcworkz)

    I would use a different approach entirely. I’d use the ‘wp_link_query_args’ filter to alter the search query arguments to include all the post statuses you want to target.

    Then to alter non-published links to target the post when published, use the ‘wp_link_query’ filter.

    Thread Starter turbodb

    (@turbodb)

    Interesting, I didn’t know about that hook – thanks!

    Seems like I might not need to do anything with the ‘wp_link_query_args’ unless I’m misunderstanding – I could just add the additional post_status in the wp_link_query (which by default filters to ‘publish’)

    But again, I’m super new to this, so would appreciate any input/feedback.

    Thread Starter turbodb

    (@turbodb)

    Nevermind, I see now that I need to modify the _args, else the list is already filtered to published.

    Giving that a shot and will report back.

    Thread Starter turbodb

    (@turbodb)

    OK, so I think I’ve got it. Probably not pretty, and I’m totally open to suggestions to make this better, but it appears to work for me (though, not sure if there are side effects elsewhere in the site as a result)

    
    function adventuretaco_wp_link_query_args( $query ) {
      //Abort early if the user will never see TinyMCE
      if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') && get_user_option('rich_editing') == 'true')
        return;
      
      // make sure we are in the admin
      $post_status_array = $query['post_status'];
      $query['post_status'] = array_push($post_status_array, 'draft', 'pending', 'auto-draft');
    
      return $query;
    }
    add_filter( 'wp_link_query_args', 'adventuretaco_wp_link_query_args' );
    
    function draft_permalink( $post_id, $current_permalink) {
      $post = get_post( $post_id );
      if (in_array($post->post_status, array('draft', 'pending', 'auto-draft'))) {
        $my_post = clone $post;
        $my_post->post_status = 'published';
        $my_post->post_name = sanitize_title($my_post->post_name ? $my_post->post_name : $my_post->post_title, $my_post->ID);
        $permalink = get_permalink($my_post);
      } else {
        $permalink = $current_permalink;
      }
      return $permalink;
    }
    
    function adventuretaco_wp_link_query( $results, $query ) {
      foreach ( $results as &$result ) {
        $result['permalink'] = draft_permalink( $result['ID'], $result['permalink'] );    	
      }
      return $results;
    }
    
    add_filter( 'wp_link_query', 'adventuretaco_wp_link_query' );
    
    • This reply was modified 6 years, 11 months ago by turbodb.
    Moderator bcworkz

    (@bcworkz)

    Looks good to me, nice work! I really doubt it’ll impact your site elsewhere. I believe the function using these filters is unique to post editor processes.

    Thread Starter turbodb

    (@turbodb)

    How expensive is get_post()? I really cringe at the fact that I’m getting *every* post again after the original query got all the posts already (with my updated query args), just so I can inspect the post_status which isn’t passed as part of $results.

    Moderator bcworkz

    (@bcworkz)

    By ID it’s pretty efficient, but all those individual queries do add up. I didn’t grasp the impact upon my initial reading. You’re right, it’s not desirable. Your callback is passed the query args used to get the list. Why don’t you rerun that query and use the results for post status? The results should match so element n of the link list will correspond to element n of the query results. Easy enough for code to verify to be sure.

    For that matter, given the post object list, you could simply rebuild the list anew, discarding the passed list. It’s a shame to throw out the initial list, but better that than doing a whole bunch of get_posts().

Viewing 7 replies - 1 through 7 (of 7 total)

The topic ‘adding a filter to post_link to link to ‘draft’ posts’ is closed to new replies.