Interesting Custom Post Type Slug with Taxonomy and Custom Field

Well if I had thought about how much work with was going to be before writing it, you wouldn’t be able to get me points right now. 🙂 Needless to say, it’s rather involved (though I don’t think it really should have to be, but it is what it is.)

First off, you can’t (easily) do it like you wanted; the problem is how to differentiate between these two URLs:

  • Event Type = “Day Time”, Event
    Title = “For a Change”

  • Event Type = “Day”, Event Title =
    “Time For a Change”

Both would have a portion of their URLs looking like this and how could we tell which is which?

day-time-for-a-change

So, I modified your pattern to use tildes (~) as separators and that works fine:

http://www.domain-name.com/events/<taxonomy-term>~event-title~<custom-field>/

Anyway, I wrote a plugin that does what you need. It does the following things:

  1. It sets the rewrite rule in the the plugin activation hook using $wp_rewrite->add_rule().

  2. It applys the pattern to create actual event post links using the 'post_type_link' hook, and

  3. It simplifes editing of the URL slug by using the 'get_sample_permalink_html' hook (I didn’t try to show the full URL because it would have been too tricky for something I’m writing for free. 🙂

So here’s what the edit screen looks like:

Screenshot of Event Edit Screen on WordPress
(source: mikeschinkel.com)

Which produces this view on the front end:

Example of Custom URLs in WordPress
(source: mikeschinkel.com)

And here ya go with the plugin code (let me know if you have questions, but not toooo many. ;-):

<?php 
/*
Plugin Name: SEO URLs for Events
*/
if (!class_exists('SeoUrlsForEvents')) {
  class SeoUrlsForEvents {
    static function on_load() {
      add_action('init', array(__CLASS__,'init'));
      add_filter('post_type_link', array(__CLASS__,'post_type_link'),10,4);
      add_filter('get_sample_permalink_html',array(__CLASS__,'get_sample_permalink_html'),10,4);
    }
    static function get_sample_permalink_html($sample, $post_id, $new_title, $new_slug) {
      $post = get_post($post_id);
      if ($post->post_type=='event') {
        $post_slug = self::make_post_slug($post);
        if ($post_slug) {
          $sample = str_replace('<strong>Permalink:</strong>','<strong>Permalink Slug:</strong>',$sample);
          $sample = preg_replace('#(<span id="sample-permalink">).+?(<span id="editable-post-name" title="Click to edit this part of the permalink">).+?</span>/</span>#Us',"$1$2{$post->post_name}</span></span>",$sample);
          $permalink = get_post_permalink($id);
          $sample = preg_replace("#(<span id='view-post-btn'><a href="https://wordpress.stackexchange.com/questions/7468/).+?(" class="button" target="_blank">View Post</a></span>)#","$1{$permalink}$2",$sample);
        }
      }
      return $sample;
    }
    static function make_post_slug($post) {
      $post_slug = false;
      $post = (object)$post;
      if ($post->post_type=='event') {
        $when = get_post_meta($post->ID,'when',true);
        if (!empty($when)) { // If we don't have a when, use default
          $types = wp_get_object_terms($post->ID,'event-type');
          if (count($types)) // If we don't have an event-type, use default else use the first one
            $post_slug = "{$types[0]->slug}~{$post->post_name}~{$when}/";
        }
      }
      return $post_slug;
    }
    static function post_type_link($post_link, $post, $leavename, $sample) {
      if ($post->post_type=='event' && $sample) {
        $post_link = '%event%';
      } else {
        $post_slug = self::make_post_slug($post);
        if ($post_slug) {
          $post_link = get_bloginfo('wpurl') . '/events/' . $post_slug;
        }
      }
      return $post_link;
    }
    static function activate() {
      global $wp_rewrite;
      $wp_rewrite->add_rule('events/([^~]+)~([^~]+)~([^/]+)','index.php?post_type=event&taxonomy=event-type&term=$matches[1]&name=$matches[2]&meta_key=when&meta_value=$matches[3]', 'top');
      $wp_rewrite->flush_rules(false);
    }
    static function init() {
      register_post_type('event',
        array(
          'label'           => 'Events',
          'public'          => true,
          'rewrite'         => array('slug' => 'events'),
          'hierarchical'    => false,
          'supports'        => array('title','editor','custom-fields'),
        )
      );
      register_taxonomy('event-type', 'event', array(
        'hierarchical'    => false,
        'label'           => 'Event Types',
        'rewrite'         => array('slug' => 'event-types' ),
        )
      );
    }
  }
  SeoUrlsForEvents::on_load();
}
register_activation_hook(__FILE__,array('SeoUrlsForEvents','activate'));

Leave a Comment