Hello!
I've a custom post type 'books', a registered taxonomy 'book_taxonomy' and some trouble with my permalinks:
I'd like my permalinks for the cpt 'books' look like this:
<blockquote>
domain.com/baseurl/--> static page with custom template 
domain.com/baseurl/[book genre]/[book name]/ --> book-article
domain.com/baseurl/[book genre]/ --> archive of all book-articles matching 'book genre'
</blockquote>
The Cherry on the cake would be a support of hierarchical taxonomies. E.g.:
<blockquote>
domain.com/baseurl/[book genre]/[book sub genre]/[book name]/ --> book-article
domain.com/baseurl/[book genre]/[book sub genre]/[...]/[book name]/ --> book-article
</blockquote>
After 'some' unsuccessful trial and error attempts based on snippets and tutorials I found on the web, I would be very thankfull for your help:-)
I think the only PHP you can use from my attempts, is this:
	add_action('init', 'post_type_books');
	function post_type_books() {
		register_post_type('books',
			array(
				'labels' => array('name' => __('Books')),
				'public' => true,
				'capability_type' => 'post',
				'has_archive' => true,
				'hierarchical' => false,
				'query_var' => true,
				'rewrite' => array('with_front'=>false)
			)
		);
	}
	add_action( 'init', 'taxonomy_books', 0 );
	function taxonomy_books() {
		register_taxonomy ('book_taxonomy',array('books'),
			array(
				'labels' => array('name' => __('Genre')),
				'show_ui' => true,
				'hierarchical' => true,
				'query_var' => true,
				'rewrite' => false
				
			)
		);
	}	
Supplement: Well, I've forgot to say that I'm not looking for a plugin-based solution... I'd like to "hardcode" it to my functions.php :-)			
Daniel Yoen answers:
								try this plugin :
http://wordpress.org/extend/plugins/custom-post-type-ui/
hope this help :)							
Daniel Yoen comments:
										try this :
<?php
	function swi_post_type_books()
		{
			register_post_type('books', array(
					'labels' => array(
							'name' => __('Books')
					),
					'public' => true,
					'capability_type' => 'post',
					'has_archive' => true,
					'hierarchical' => false,
					'query_var' => true,
					'publicly_queryable' => true,
					'query_var' => true,
					'rewrite' => false
			));
			register_taxonomy('books_taxonomy', array(
					'books'
			), array(
					'labels' => array(
							'name' => __('Genre')
					),
					'show_ui' => true,
					'hierarchical' => true,
					'query_var' => true,
					'rewrite' => false
			));
		}
	function swi_custom_rewrite_post_type()
		{
			global $wp_rewrite;
			add_rewrite_tag('%books_cat%', '([^/]+)');
			add_rewrite_tag('%books_subcat%', '([^/]+)');
			$books_structure = '/mybooks/%books_cat%/%books_subcat%/%books%';
			$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
			$wp_rewrite->add_permastruct('books', $books_structure, false);
		}
	function swi_books_permalink($permalink, $post_id, $leavename)
		{
			$post        = get_post($post_id);
			$rewritecode = array(
					'%year%',
					'%monthnum%',
					'%day%',
					'%hour%',
					'%minute%',
					'%second%',
					$leavename ? '' : '%postname%',
					'%post_id%',
					'%category%',
					'%author%',
					$leavename ? '' : '%pagename%',
					'%books_cat%',
					'%books_subcat%'
			);
			if ('' != $permalink && !in_array($post->post_status, array(
					'draft',
					'pending',
					'auto-draft'
			)))
				{
					$unixtime = strtotime($post->post_date);
					$category = '';
					if (strpos($permalink, '%category%') !== false)
						{
							$cats = get_the_category($post->ID);
							if ($cats)
								{
									usort($cats, '_usort_terms_by_ID');
									$category = $cats[0]->slug;
									if ($parent = $cats[0]->parent)
											$category = get_category_parents($parent, false, '/', true) . $category;
								}
							if (empty($category))
								{
									$default_category = get_category(get_option('default_category'));
									$category         = is_wp_error($default_category) ? '' : $default_category->slug;
								}
						}
					$post_type   = $post->post_type;
					$books_cat = '';
					$cat_parent  = '';
					if (strpos($permalink, '%books_cat') !== false)
						{
							$terms = wp_get_object_terms($post->ID, 'books_taxonomy');
							if (!is_wp_error($terms) && !empty($terms))
								{
									foreach ($terms as $term)
										{
											if ($term->parent == 0)
												{
													$books_cat = $term->slug;
													$cat_parent  = $term->term_id;
													break;
												}
										}
								}
						}
					$books_subcat = '';
					if (strpos($permalink, '%books_subcat%') !== false && !empty($cat_parent))
						{
							foreach ($terms as $term)
								{
									if ($term->parent == $cat_parent)
										{
											$books_subcat = $term->slug;
											break;
										}
								}
						}
					$author = '';
					if (strpos($permalink, '%author%') !== false)
						{
							$authordata = get_userdata($post->post_author);
							$author     = $authordata->user_nicename;
						}
					$date           = explode(" ", date('Y m d H i s', $unixtime));
					$rewritereplace = array(
							$date[0],
							$date[1],
							$date[2],
							$date[3],
							$date[4],
							$date[5],
							$post->post_name,
							$post->ID,
							$category,
							$author,
							$post->post_name,
							$books_cat,
							$books_subcat
					);
					$permalink      = str_replace($rewritecode, $rewritereplace, $permalink);
				}
			else
				{
				}
			return $permalink;
		}
	add_action('init', 'swi_post_type_books');
	add_action('init', 'swi_custom_rewrite_post_type');
	add_filter('post_type_link', 'swi_books_permalink', 10, 3);
?>
hope this help :)									
Daniel Yoen comments:
same code, better looks. :)
Daniel Yoen comments:
										Sorry.
<?php
	function swi_post_type_books()
		{
			register_post_type('books', array(
					'labels' => array(
							'name' => __('Books')
					),
					'public' => true,
					'capability_type' => 'post',
					'has_archive' => true,
					'hierarchical' => false,
					'query_var' => true,
					'publicly_queryable' => true,
					'query_var' => true,
					'rewrite' => false
			));
			register_taxonomy('books_taxonomy', array(
					'books'
			), array(
					'labels' => array(
							'name' => __('Genre')
					),
					'show_ui' => true,
					'hierarchical' => true,
					'query_var' => true,
					'rewrite' => false
			));
		}
	function swi_custom_rewrite_post_type()
		{
			global $wp_rewrite;
			add_rewrite_tag('%books_cat%', '([^/]+)');
			add_rewrite_tag('%books_subcat%', '([^/]+)');
			$books_structure = '/mybooks/%books_cat%/%books_subcat%/%books%';
			$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
			$wp_rewrite->add_permastruct('books', $books_structure, false);
		}
	function swi_books_permalink($permalink, $post_id, $leavename)
		{
			$post        = get_post($post_id);
			$rewritecode = array(
					'%year%',
					'%monthnum%',
					'%day%',
					'%hour%',
					'%minute%',
					'%second%',
					$leavename ? '' : '%postname%',
					'%post_id%',
					'%category%',
					'%author%',
					$leavename ? '' : '%pagename%',
					'%books_cat%',
					'%books_subcat%'
			);
			if ('' != $permalink && !in_array($post->post_status, array(
					'draft',
					'pending',
					'auto-draft'
			)))
				{
					$unixtime = strtotime($post->post_date);
					$category = '';
					if (strpos($permalink, '%category%') !== false)
						{
							$cats = get_the_category($post->ID);
							if ($cats)
								{
									usort($cats, '_usort_terms_by_ID');
									$category = $cats[0]->slug;
									if ($parent = $cats[0]->parent)
											$category = get_category_parents($parent, false, '/', true) . $category;
								}
							if (empty($category))
								{
									$default_category = get_category(get_option('default_category'));
									$category         = is_wp_error($default_category) ? '' : $default_category->slug;
								}
						}
					$post_type   = $post->post_type;
					$books_cat = '';
					$cat_parent  = '';
					if (strpos($permalink, '%books_cat') !== false)
						{
							$terms = wp_get_object_terms($post->ID, 'books_taxonomy');
							if (!is_wp_error($terms) && !empty($terms))
								{
									foreach ($terms as $term)
										{
											if ($term->parent == 0)
												{
													$books_cat = $term->slug;
													$cat_parent  = $term->term_id;
													break;
												}
										}
								}
						}
					$books_subcat = '';
					if (strpos($permalink, '%books_subcat%') !== false && !empty($cat_parent))
						{
							foreach ($terms as $term)
								{
									if ($term->parent == $cat_parent)
										{
											$books_subcat = $term->slug;
											break;
										}
								}
						}
					$author = '';
					if (strpos($permalink, '%author%') !== false)
						{
							$authordata = get_userdata($post->post_author);
							$author     = $authordata->user_nicename;
						}
					$date           = explode(" ", date('Y m d H i s', $unixtime));
					$rewritereplace = array(
							$date[0],
							$date[1],
							$date[2],
							$date[3],
							$date[4],
							$date[5],
							$post->post_name,
							$post->ID,
							$category,
							$author,
							$post->post_name,
							$books_cat,
							$books_subcat
					);
					$permalink      = str_replace($rewritecode, $rewritereplace, $permalink);
				}
			else
				{
				}
			return $permalink;
		}
	add_action('init', 'swi_post_type_books');
	add_action('init', 'swi_custom_rewrite_post_type');
	add_filter('post_type_link', 'swi_books_permalink', 10, 3);
?>
mark comments:
										Hey Daniel,
Wow, what a monster*... and a realy good start! :-) :-) :-)
- this code works perfectly for cpt posts with extactly two selected hierachical (sub)categories :-)
but...
- it doesn't work if only a maincategory is selected (or the category-depth is deeper then 2)
- it doesn't show archive-pages for links like
<blockquote>domain.com/mybooks/[book genre]/ --> archive of all book-articles matching 'book genre'</blockquote>
Any Ideas how we can achieve that? This last point is very important for me. Currently the homepage shows up when requesting an URL like "mysite.com/mybooks/sciencefiction/", but I'd like to see an achive-page of all scifi-books (shown by the matching template 'achive-books.php')
*) I removed all the unnecessary code and 'slimmed' it a little bit (still works like the code above):
	function swi_post_type_books(){
		register_post_type('books', array(
				'labels' => array(
						'name' => __('Books')
					),
				'public' => true,
				'capability_type' => 'post',
				'has_archive' => true,
				'hierarchical' => false,
				'query_var' => true,
				'publicly_queryable' => true,
				'query_var' => true,
				'rewrite' => false
			)
		);
		register_taxonomy('books_taxonomy', array('books'),
			array(
				'labels' => array(
						'name' => __('Genre')
				),
				'show_ui' => true,
				'hierarchical' => true,
				'query_var' => true,
				'rewrite' => false
			)
		);
	}
	function swi_custom_rewrite_post_type(){
		global $wp_rewrite;
		add_rewrite_tag('%books_cat%', '([^/]+)');
		add_rewrite_tag('%books_subcat%', '([^/]+)');
		$books_structure = '/mybooks/%books_cat%/%books_subcat%/%books%';
		$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
		$wp_rewrite->add_permastruct('books', $books_structure, false);
	}
	
	
	function swi_books_permalink($permalink, $post_id, $leavename){
		$post = get_post($post_id);
		
		$rewritecode = array(
			'%books_cat%',
			'%books_subcat%'
		);
		if ('' != $permalink && !in_array($post->post_status, array('draft','pending','auto-draft'))){
			$books_cat = '';
			$cat_parent  = '';
			if (strpos($permalink, '%books_cat') !== false){
				$terms = wp_get_object_terms($post->ID, 'books_taxonomy');
				if (!is_wp_error($terms) && !empty($terms))	{
					foreach ($terms as $term){
						if ($term->parent == 0)	{
							$books_cat = $term->slug;
							$cat_parent  = $term->term_id;
							break;
						}
					}
				}
			}
			$books_subcat = '';
			if (strpos($permalink, '%books_subcat%') !== false && !empty($cat_parent)){
				foreach ($terms as $term){
					if ($term->parent == $cat_parent){
							$books_subcat = $term->slug;
							break;
					}
				}
			}
			$rewritereplace = array(
				$books_cat,
				$books_subcat
			);
			$permalink = str_replace($rewritecode, $rewritereplace, $permalink);
			
		}		
		
		return $permalink;
	}
	add_action('init', 'swi_post_type_books');
	add_action('init', 'swi_custom_rewrite_post_type');
	add_filter('post_type_link', 'swi_books_permalink', 10, 3);
I'll have to say: I had no idea that all this might be that complicated! :)									
Daniel Yoen comments:
										Hello, Try this :)
<?php
	function swi_post_type_books()
		{
			register_post_type('books', array(
					'labels' => array(
							'name' => __('Books')
					),
					'public' => true,
					'capability_type' => 'post',
					'has_archive' => true,
					'hierarchical' => true,
					'query_var' => true,
					'publicly_queryable' => true,
					'query_var' => true,
					'rewrite' => array('slug' => '/mybooks/%cat%/%subcat%', 'with_front' => true)
			));
			register_taxonomy('mybooks', array('books'
			), array(
					'labels' => array(
							'name' => __('Genre')
					),
					'show_ui' => true,
					'hierarchical' => true,
					'query_var' => true,
					'rewrite' => true
			));
			global $wp_rewrite;
			add_rewrite_tag('%cat%', '([^/]+)');
			add_rewrite_tag('%subcat%', '([^/]+)');
			add_rewrite_tag("%books%", '([^/]+)', "books=");
			$wp_rewrite->add_permastruct('books', '/mybooks/%cat%/%subcat%/%books%', false);
		}
	add_action('init', 'swi_post_type_books');
	function swi_books_permalink($permalink, $post_id, $leavename)
		{
			$post        = get_post($post_id);
			$rewritecode = array('%cat%', '%subcat%');
			if ('' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')))
				{
					$post_type   = $post->post_type;
					$cat = '';
					$cat_parent  = '';
					if (strpos($permalink, '%cat%') !== false)
						{
							$terms = wp_get_object_terms($post->ID, 'mybooks');
							if (!is_wp_error($terms) && !empty($terms))
								{
									foreach ($terms as $term)
										{
											if ($term->parent == 0)
												{
													$cat = $term->slug;
													$cat_parent  = $term->term_id;
													break;
												}
										}
								}
						}
					$subcat = '';
					if (strpos($permalink, '%subcat%') !== false && !empty($cat_parent))
						{
							foreach ($terms as $term)
								{
									if ($term->parent == $cat_parent)
										{
											$subcat = $term->slug;
											break;
										}
								}
						}
					$rewritereplace = array($cat, $subcat);
					$permalink      = str_replace($rewritecode, $rewritereplace, $permalink);
				}
			else
				{
				}
			return $permalink;
		}
	add_filter('post_type_link', 'swi_books_permalink', 10, 3);
	function swi_rewrite_flush()
		{
			global $wp_rewrite;
			$wp_rewrite->flush_rules();
		}
	add_action('init','swi_rewrite_flush');
?>
Hope this help :)									
mark comments:
										Hey Daniel,
sorry to say, but: no effect :-/
The code isn't able to "decide" whether to call an archive OR an post... 
As I read the php the book-permalink structure is still "static" (/mybooks/%cat%/%subcat%). So it works only if exactly 2 hierachical categories are selected:-(
I think we need somthing more flexible, maybe something completly different?
Hm... 									
Daniel Yoen comments:
										I've tested it and succeeded in wordpress 3.4
/mybooks/%cat%/%subcat%/%postname%/ | works
/mybooks/%cat%/ | works
In my view. :D									
mark comments:
										hey Daniel,
I just send you an message with the live-example.. it realy doesn't work... :-( and if it would, I would wonder why?
I can't see a function/ section which could do what I've requested... maybe I'm wrong.. but could you please explain how an archive will be displayed by the code posted above? :-)
Thanks
:-))									
mark comments:
										Hey Daniel,
thanks again. The new code works fine for me - no sub-(sub...)-categories, but I can live with that at the moment.
Thanks a lot!
Mark									
Arnav Joy answers:
								try this
	add_action('init', 'post_type_books');							
	function post_type_books() {
		register_post_type('books',
			array(
				'labels' => array('name' => __('Books')),
				'public' => true,
				'capability_type' => 'post',
				'has_archive' => true,
				'hierarchical' => false,
				'query_var' => true,
				'rewrite' => array('with_front'=>false)
			)
		);
	}
	add_action( 'init', 'taxonomy_books', 0 );
	function taxonomy_books() {
		register_taxonomy ('book_taxonomy',array('books'),
			array(
				'labels' => array('name' => __('Genre')),
				'show_ui' => true,
				'hierarchical' => true,
				'query_var' => true,
				'rewrite' => true
				
			)
		);
	}	
mark comments:
										Well, no: that doesn't have any effect... I think it's not that simple:-(
I'm sure we'll have to add a filter with some new rewrite rules for the cpt. But I don't know how this filter should look like...									
Arnav Joy comments:
										write this after the above code in functions.php
flush_rewrite_rules();									
Arnav Joy comments:
										or try this
function my_em_rewrite_flush(){									
	global $wp_rewrite;
   	$wp_rewrite->flush_rules();
}
add_action('init','my_em_rewrite_flush');
Arnav Joy comments:
										try this
add_action( 'init', 'taxonomy_books', 0 );									
	function taxonomy_books() {
		register_taxonomy ('book_taxonomy',array('books'),
			array(
				'labels' => array('name' => __('Genre')),
				'show_ui' => true,
				'hierarchical' => true,
				'query_var' => true,
			    'rewrite' => array( 'slug' => 'books/type' ),
				
			)
		);
	}
Arnav Joy comments:
										you can check this plugin
http://wordpress.org/extend/plugins/permalinks-for-hierarchical-custom-post-types/									
mark comments:
										Hey Arnav,
thanks for your help, but I think this isn't the way we'll get it to work :-) I'm quite sure we'll HAVE to set up and add some specific rewrite rules.
Somthink like this or maybe not:
global $wp_rewrite;
$book_structure = '/mybooks/%book_taxonomy%/%books%';
$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
$wp_rewrite->add_permastruct('books', $book_structure, false);
And we'll have to add a filter to translate the permalink tags. Somthink like that could be found here:
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2
But as I said: I already worked on an trial and error 'method' on this for 'some' hours and couldn't get it working.
Flushing the rules without defining new ones can not have any effect - am I wrong?
BTW, another question: Is there any difference between flush_rewrite_rules(); and ? In the past I've only used the first one...
	function my_em_rewrite_flush(){
		global $wp_rewrite;
		$wp_rewrite->flush_rules();
	}
	add_action('init','my_em_rewrite_flush');
Plugin: As I wrote, I'm not looking for a plugin-based solution... I realy NEED to hardcode the rules into my functions.php  :-/