Ok, so I'm doing a new project and we're going to be using Wordpress as a magazine CMS. In some cases we'll have a cluster of articles about a topic and it will be natural to link from one article to another. So, here we are in final edit in WP.
We want to add a link from one draft article to another draft article in the cluster, but the target article hasn't been published, so WP doesn't show it in the Link to Existing Content box. Sure, I can get the shortlink for the draft of the article I want to link to, but then I need to open that tab, get the shortlink (or the draft's slug), move back to the post that I want to link from, add the link. Doing this occasionally is fine but as a constant task it's crappy workflow.

Now, we can simply publish and then hurriedly go through the articles and link things, but that's suboptimal. I can't imagine all of the magazines and other sites that do periodical publishing with WP do that though. I'll play with Editflow to see if it has a way to deal with this, but does anyone know of a way to link from one draft to another and have the link be correct when they're both published?

And yes, I know I can link things up after publishing. See 'crappy workflow'.

1 Answer 1


This is very similar to this question.

We have to hook into check_ajax_referer to address the internal linking feature only. Then we register an action for pre_get_posts to extend the search to drafts and pending posts.

We will still get no pretty permalinks, because they are excluded in get_permalink. So we register a filter for that too and ask WordPress again for a permalink, but with a faked post status.

As code:

add_action( 'check_ajax_referer', 'internal_links_for_drafts' );

 * Extend search for internal links to 'draft' and 'pending' statuses.
 * @wp-hook check_ajax_referer
 * @wp-hook pre_get_posts
 * @param string|WP_Query $var
 * @return boolean|void
function internal_links_for_drafts( $var )
    if ( 'check_ajax_referer' === current_filter() && 'internal-linking' === $var )
        return add_action( 'pre_get_posts', __FUNCTION__ );

    // now we are in the 'pre_get_posts' action.
    $var->set( 'post_status', array( 'publish', 'pending', 'draft' ) );
    remove_action( 'pre_get_posts', __FUNCTION__ );
    add_filter( 'post_link', 'draft_permalink', 10, 2 );
 * Get permalink for drafts and pending posts.
 * Dangerous, because their title can still change.
 * @param  string $permalink
 * @param  object $post
 * @return string
function draft_permalink( $permalink, $post )
    remove_filter( current_filter(), __FUNCTION__ );

    // swap status temporary
    $original_status   = $post->post_status;
    $post->post_status = 'publish';
    $url               = get_permalink( $post );
    $post->post_status = $original_status;

    return $url;
  • Perfect. I could have hacked the core file that builds this dialog of course, but that's a Bad Thing To Do. This works well, much appreciated. Jun 5, 2013 at 19:40
  • Shame this isn't a plugin rather than a hack.
    – Jules
    Apr 10, 2018 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.