Update Old Links To Pretty Permalinks Custom Post Type

I’m looking for a plug-in or bit of php that will go through about 300 posts that use hyperlinks in the old p format:

<a href="http://mysite.com/?p=3592">

and automatically replace them with their %postname% pretty permalink. Eg:

Read More
<a href="http://mysite.com/my-post-about-whatever">

For whatever reason, these posts don’t auto-magically do this when we changed Permalink structure so we’re currently going through one by one. Thousands of links. I -think- the problem is that we originally imported them from static HTML pages.

I’m wondering if the fact that they don’t automatically re-write is because we’re using a Custom Post Type?

OR, is there a problem with the way we set up the taxonomy that prevents the automatic rewrite? If so, can someone provide some suggestions. Here’s our taxonomy for this Custom Post Type (docs)

//helpdocs taxonomy
add_action( 'init', 'create_docs_post_type' );
function create_docs_post_type() {
$labels = array(
    'name' => __( 'Documentation' ),
    'singular_name' => __( 'Documentation' )
  );
    $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'show_in_menu' => true,
    'query_var' => true,
    'rewrite' => true,
    'capability_type' => 'page',
    'has_archive' => true,
    'hierarchical' => true,
    'menu_position' => 50,
    'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt',
    'comments',     'custom-fields', 'revisions','page-attributes','post-formats' )
  );    

register_post_type( 'docs', $args);
}
function docs_init() {
// create a new taxonomy
register_taxonomy(
    'docs_tax',
    'docs',
    array(
        'label' => __( 'Documentation_Tax' ),
        'sort' => true,
        'args' => array( 'orderby' => 'term_order' ),
    'hierarchical' => true,
        'rewrite' => array( 'slug' => 'docs' )

    )
);
}
add_action( 'init', 'docs_init' );

TIA,

—JC

Related posts

1 comment

  1. You can cycle your posts, extract urls and then look at the query vars in them to create the proper link, an finally replace old links with new in post_content.

    This kind of work should be runned once, so I suggest to create a plugin and run this function on deactivation.

    I also created an helper function to extract urls from post content. WP 3.7 comes with a core function wp_extract_urls, however this function return url without query vars, so is useless for our scope.

    <?php
    /**
     * Plugin Name: Url Replacer
     * Author: G.M.
     */
    
    register_deactivation_hook( __FILE__, 'gm_replace_my_old_urls' );
    
    function my_extract_urls( $content ) {
      preg_match_all("#<a.*?href=["'](http[s]*://[^>"]*?)["'][^>]*?>(.*?)</a>#si", $content, $urls);  
      $urls = array_unique( array_map( 'html_entity_decode', $urls[1] ) );
      return array_values( $urls );
    }
    
    function gm_replace_my_old_urls() {
      $query = new WP_Query( array('posts_per_page' => -1) );
      if ( empty($query->posts) ) return;
      foreach ( $query->posts as $post ) {
        $urls = my_extract_urls($post->post_content); 
        if ( empty($urls) ) continue;
        $new = array();
        $old = array();
        foreach ( $urls as $url ) {
          if ( ! substr_count( $url, home_url() ) ) continue; // external url
          $url_array = explode( '?', $url );
          $qs = array();
          if ( count($url_array) == 2 ) parse_str( $url_array[1], $qs );
          if ( ! isset($qs['p']) && ! isset($qs['page_id']) ) continue;
          $id = isset($qs['p']) ? $qs['p'] : $qs['page_id'];
          $link = get_permalink($id);
          if ( ! $link ) continue;
          $old[] = $url;
          $new[] = $link;
        }
        if ( ! empty($new) ) {
          $post = (array)$post;
          $post['post_content'] = str_replace($old, $new, $post['post_content']);
          wp_update_post($post);
        }
      }
    }
    

    Save this code in a file and save in plugin folder. After that go in your dashboard and activate it. Nothing should happen. Now disable the plugin. It should take some seconds when plugin is deactivated go to check your posts…

Comments are closed.