Sometimes in WordPress we might run into a situation where we need a little more control over a taxonomy or we need to associate a post with several other posts. There are several ways to do this such as using meta fields, custom taxonomies and so on. In the example below describes how you can create a new post type and automatically generate a custom taxonomy based off the post type. Sounds a little complicated, not really you will see how simple it is and how it could be useful in many ways.

The other code snippets will also show you how to convert already existing custom post types into a taxonomy and how to retrieve a post with all it’s associated custom post types. To make this situation more clear let us assume you have  a music blog and would like to write about an artist which we would consider as a regular post. Now we have a custom post type called music genres and in some cases we would have an artist associated with more than one genre. Here if we really wanted to provide information about a genre including image, meta fields, etc we would not be able to use the regular taxonomy provided by WordPress. Thus custom post types converted into a taxonomy would help accomplish this.

function initialize_music_post_types(){
   // custom post type for music_genre
   register_post_type('music_genre',
                      array(
                      'labels' => array(
                                   'name' => _x('Music Genre'),
                                   'singular_name' => _x('Music Genre'),
                                   'add_new' => _x('Add New', 'Music Genre'),
                                   'add_new_item' => __('Add New Music Genre'),
                                   'edit_item' => __('Edit Music Genre'),
                                   'new_item' => __('New Music Genre'),
                                   'view_item' => __('View Music Genre'),
                                   'search_items' => __('Search Music Genres'),
                                   'not_found' =>  __('No Music Genres found'),
                                   'not_found_in_trash' => __('No music genres in Trash'),
                                   'parent_item_colon' => ''
                                   ),
                      'public' => true,
                      'publicly_queryable' => true,
                      'query_var' => 'music_genre',
                      'rewrite' => array('slug'=>'music_genre', 'with_front'=>false),
                      'capability_type' => 'post',
                      'hierarchical' => true,
                      'supports' => array('title', 'editor', 'thumbnail',),
                   ));
   // register a taxonomy
   register_taxonomy('music_genre_posts',
                     array('post'),
                     array(
                      'label' => __('Music Genres'),
                      'singular_label' => __('Music Genre'),
                      'hierarchical' => true,
                      'query_var' => 'music_genre_posts',
                      'rewrite' => false,
                      'public' => true,
                      'show_ui' => null,
                      'show_in_nav_menus' => false,
                   ));
}

function post_music_update($post_id){
  if(wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
      return $post_id;
  }

  $post_obj = get_post($post_id);
  $raw_title = $post_obj->post_title;
  $post_type = $post_obj->post_type;
  $slug_title = sanitize_title($raw_title);

  if (($post_type == 'music_genre') && ($slug_title != 'auto-draft') && (!empty($raw_title))) {
     // get the terms associated with this custom post type
     $terms = get_the_terms($post_id, 'music_genre_posts');
     $term_id = $terms[0]->term_id;
     // if term exists then update term
     if ($term_id > 0) {
         wp_update_term($term_id,
                        'music_genre_posts',
                        array(
                          'description' => $raw_title,
                          'slug' => $raw_title,
                          'name' => $raw_title)
                        );
     } else {
        // creates a new term in the music_genre_posts taxonomy
        wp_set_object_terms($post_id, $raw_title, 'music_genre_posts', false);
     }
  }
}

add_action( 'init', 'initialize_music_post_types' );
add_action('save_post', 'post_music_update');

The code above registers a custom post type and the filter save_post which creates a term every time a post in the music genre custom post type is created. It also takes care of updates and auto saves. So when a user creates a new post in the music genre custom post type it creates a new term in the music_genre_posts taxonomy and the term is named the same as the title of the post. If you need to update or edit a post the function checks if a term is associated with that custom post and then updates the term.

/**
 * Create slugs/terms in music_genre_posts taxonomy for all music_genres
 *
 */
function make_taxonomy_from_posts($post_type, $taxonomy){
   // Get all posts
   $query_posts = query_posts(array(
                             // ... of the requested type
                             'post_type'=> $post_type,
                             // ... and it supports the taxonomy
                             'taxonomy' => $taxonomy,
                             // ... without limit
                             'nopaging' => true,
                  ));

  // Reset the main query
  wp_reset_query();

  foreach ($query_posts as $query_post) {
      $post_id = $query_post->ID;
      $raw_title = $query_post->post_title;
      // Generate a slug based on the title.
      // We want to check for auto-draft so we don't create a term for a post with no title
      $slug_title = sanitize_title($raw_title);

      // Do the checks for empty titles
      // If the title is blank, skip it
      if ($slug_title == 'auto-draft' || empty($raw_title)) continue;
      // Get all of the terms associated with the post
      $terms = get_the_terms($post_id, $taxonomy);
      $term_id = 0;

      if (!empty($terms)) {
           $term_id = $terms[0]->term_id;
      }

     if ($term_id > 0) {
          // If the post has a term, update the term
          wp_update_term($term_id, $taxonomy, array(
                                               'description' => $raw_title,
                                               'slug' => $raw_title,
                                               'name' => $raw_title,
                         ));
     } else {
         // Otherwise add a new term
         wp_set_object_terms($post_id, $raw_title, $taxonomy, false);
     }
  }
}

The function make_taxonomy_from_posts queries all existing music_genre custom post types and creates terms, slugs and descriptions for each one of those posts. This can be run once if you want to convert existing custom post types into a taxonomy by specifying the post type and the name of the taxonomy.

/**
* Returns an array of music genres associated with a post
*
*/
function get_the_music_genres($post_id = 0) {
  if (!$post_id) {
      $post_id = get_the_ID();
  }

  $music_genres = array();
  // Get all of the music_genre_posts (taxonomy) associated with the post
  $terms = wp_get_object_terms($post_id, 'music_genre_posts');

  if (!empty($terms)) {
     foreach ($terms as $term) {
         // Get the music genre (post) associated with each term
         $music_genre = array_shift(query_posts(array(
                                                 'post_type' => 'music_genre',
                                                 'music_genre_posts' => $term->slug,
                                   )));
         wp_reset_query();

         if (!empty($music_genre)) {
             $music_genres[] = $music_genre;
         }
     }
   return $music_genres;
 }
 return FALSE;
}

The function get_music_genres retrieves all music genres associated with that post. It querys all posts and matches them based on post type and slug of the post. Thus returning all the custom post types associated with the post.

 

2 Responses to WordPress: Convert custom post type into taxonomy/category

  1. Michael says:

    This is so close to what I need I think. I have a custom post type of ‘artists’ which originally used the standard ‘categories’ taxonomy. I have created a new custom taxonomy called ‘genres’. My issue now is that I need to convert all of the 450+ ‘artists’ categories, to the new taxonomy ‘genres’.

    I don’t want to create a custom taxonomy for each category, just map the current categories to the custom taxonomy ‘genres’.

    Any ideas?
    Thanks in advance!!

  2. admin says:

    I am a little confused here so do you want to assign all your artist posts to the same categories as present in default taxonomy to the new taxonomy you created called genres.

    In that case you dont need to create a custom taxonomy for each genre category. But you will have to do a check to see if that term/category is also present under your genre category or else insert that term/category into the genre taxonomy and then assign your artist posts to those genre categories based on a matching term slug.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>