How to fix a double slash in custom permalinks with hierarchical taxonomy’s?

Following the solution from Jeff @ Custom permalinks – post type – hierarchical taxonomy’s

I managed to rewrite my url’s for custom taxonomy’s.
However i do have one thing that bothers me and that is a double slash in the output because of the separator.

Read More

http://www.domain.nl/product/televisies/led/55-inch//product-naam-4/

I can not change this in the permalinks section in de admin. (/%category%/%postname%/)

register_post_type( "products", 
            array(  'label'             => CUSTOM_MENU_TITLE,
                    'labels'            => array(   'name'                  =>  CUSTOM_MENU_NAME,
                                                    'singular_name'         =>  CUSTOM_MENU_SIGULAR_NAME,
                                                    'add_new'               =>  CUSTOM_MENU_ADD_NEW,
                                                    'add_new_item'          =>  CUSTOM_MENU_ADD_NEW_ITEM,
                                                    'edit'                  =>  CUSTOM_MENU_EDIT,
                                                    'edit_item'             =>  CUSTOM_MENU_EDIT_ITEM,
                                                    'new_item'              =>  CUSTOM_MENU_NEW,
                                                    'view_item'             =>  CUSTOM_MENU_VIEW,
                                                    'search_items'          =>  CUSTOM_MENU_SEARCH,
                                                    'not_found'             =>  CUSTOM_MENU_NOT_FOUND,
                                                    'not_found_in_trash'    =>  CUSTOM_MENU_NOT_FOUND_TRASH ),
                    'public'            => true,
                    'can_export'        => true,
                    'show_ui'           => true, // UI in admin panel
                    '_builtin'          => false, // It's a custom post type, not built in
                    '_edit_link'        => 'post.php?post=%d',
                    'capability_type'   => 'post',
                    'menu_icon'         => get_bloginfo('template_url').'/images/favicon.ico',
                    'hierarchical'      => true,
                    'rewrite'           => array('slug' => 'product/%taxonomy_name%','with_front' => true,'hierarchical'=>true), // Permalinks
                    'query_var'         => "products", // This goes to the WP_Query schema
                    'supports'          => array(   'title',
                                                    'author', 
                                                    'excerpt',
                                                    'thumbnail',
                                                    'comments',
                                                    'editor', 
                                                    'trackbacks',
                                                    'custom-fields',
                                                    'revisions') ,
                    'show_in_nav_menus' => true ,
                    'taxonomies'        => array("pcategory","ptags")
                )
            );

// Register custom taxonomy
register_taxonomy(  "pcategory", 
            array(  "products"  ), 
            array ( "hierarchical"      => true, 
                    "label"             => CUSTOM_MENU_CAT_LABEL, 
                    'labels'            => array(   'name'              =>  CUSTOM_MENU_CAT_TITLE,
                                                    'singular_name'     =>  CUSTOM_MENU_SIGULAR_CAT,
                                                    'search_items'      =>  CUSTOM_MENU_CAT_SEARCH,
                                                    'popular_items'     =>  CUSTOM_MENU_CAT_SEARCH,
                                                    'all_items'         =>  CUSTOM_MENU_CAT_ALL,
                                                    'parent_item'       =>  CUSTOM_MENU_CAT_PARENT,
                                                    'parent_item_colon' =>  CUSTOM_MENU_CAT_PARENT_COL,
                                                    'edit_item'         =>  CUSTOM_MENU_CAT_EDIT,
                                                    'update_item'       =>  CUSTOM_MENU_CAT_UPDATE,
                                                    'add_new_item'      =>  CUSTOM_MENU_CAT_ADDNEW,
                                                    'new_item_name'     =>  CUSTOM_MENU_CAT_NEW_NAME,   ), 
                    'public'            => true,
                    'show_ui'           => true,
                    "rewrite"           => array('slug' => 'product','with_front' => true,'hierarchical'=>true))
            ); 

My functions.php includes:

add_filter('rewrite_rules_array', 'mmp_rewrite_rules');
function mmp_rewrite_rules($rules) {
$newRules  = array();
$newRules['product/(.+)/(.+)/(.+)/(.+)/?$'] = 'index.php?products=$matches[4]';
$newRules['product/(.+)/?$']                = 'index.php?pcategory=$matches[1]'; 

return array_merge($newRules, $rules);
}
function filter_post_type_link($link, $post)
{
if ($post->post_type != 'products')
    return $link;

if ($cats = get_the_terms($post->ID, 'pcategory'))
{
    $link = str_replace('%taxonomy_name%', get_taxonomy_parents(array_pop($cats)->term_id, 'pcategory', false, '/', true), $link);
}
return $link;
}
add_filter('post_type_link', 'filter_post_type_link', 10, 2);

// my own function to do what get_category_parents does for other taxonomies
function get_taxonomy_parents($id, $taxonomy, $link = false, $separator = '/', $nicename = false, $visited = array()) {    
$chain = '';   
$parent = &get_term($id, $taxonomy);

if (is_wp_error($parent)) {
    return $parent;
}

if ($nicename)    
    $name = $parent -> slug;        
else    
    $name = $parent -> name;

if ($parent -> parent && ($parent -> parent != $parent -> term_id) && !in_array($parent -> parent, $visited)) {    
    $visited[] = $parent -> parent;    
    $chain .= get_taxonomy_parents($parent -> parent, $taxonomy, $link, $separator, $nicename, $visited);
}

if ($link) {
    // nothing, can't get this working :(
} else    
    $chain .= $name . $separator;
return $chain;    
}

Does any one know how to solve this?

Related posts

Leave a Reply

4 comments

  1. There is a quick and somewhat dirty potential solution to this. I say ‘potential’ because I can’t spot the problem by looking at the code. I only have my suspicions. Instead of passing a separator like that. Try trailingslashit.

    } else    
        $chain .= trailingslashit($name);
    return $chain;  
    

    I am guessing at where the problem is based on your description, but that is the only place that $separator is applied.

    There is a case where this simple fix won’t work. If $name is empty, you will get an extra slash in your string, so it would be better to check for that, just in case.

    } elseif (!empty($name))     
        $chain .= trailingslashit($name);
    return $chain;
    

    Try that.

  2.     $link = str_replace('%taxonomy_name%', get_taxonomy_parents(array_pop($cats)->term_id, 'pcategory', false, '/', true), $link);
    

    needs to become

        $link = str_replace('%taxonomy_name%', get_taxonomy_parents(array_pop($cats)->term_id, 'pcategory', false, true), $link);
    

    Otherwise the revised function errors out looking for the separator.

  3. After changing something i have the final code that makes it work.

    This is where you register the post types. (not changed)

    register_post_type( "products", 
                array(  'label'             => CUSTOM_MENU_TITLE,
                        'labels'            => array(   'name'                  =>  CUSTOM_MENU_NAME,
                                                        'singular_name'         =>  CUSTOM_MENU_SIGULAR_NAME,
                                                        'add_new'               =>  CUSTOM_MENU_ADD_NEW,
                                                        'add_new_item'          =>  CUSTOM_MENU_ADD_NEW_ITEM,
                                                        'edit'                  =>  CUSTOM_MENU_EDIT,
                                                        'edit_item'             =>  CUSTOM_MENU_EDIT_ITEM,
                                                        'new_item'              =>  CUSTOM_MENU_NEW,
                                                        'view_item'             =>  CUSTOM_MENU_VIEW,
                                                        'search_items'          =>  CUSTOM_MENU_SEARCH,
                                                        'not_found'             =>  CUSTOM_MENU_NOT_FOUND,
                                                        'not_found_in_trash'    =>  CUSTOM_MENU_NOT_FOUND_TRASH ),
                        'public'            => true,
                        'can_export'        => true,
                        'show_ui'           => true, // UI in admin panel
                        '_builtin'          => false, // It's a custom post type, not built in
                        '_edit_link'        => 'post.php?post=%d',
                        'capability_type'   => 'post',
                        'menu_icon'         => get_bloginfo('template_url').'/images/favicon.ico',
                        'hierarchical'      => true,
                        'rewrite'           => array('slug' => 'product/%taxonomy_name%','with_front' => true,'hierarchical'=>true), // Permalinks
                        'query_var'         => "products", // This goes to the WP_Query schema
                        'supports'          => array(   'title',
                                                        'author', 
                                                        'excerpt',
                                                        'thumbnail',
                                                        'comments',
                                                        'editor', 
                                                        'trackbacks',
                                                        'custom-fields',
                                                        'revisions') ,
                        'show_in_nav_menus' => true ,
                        'taxonomies'        => array("pcategory","ptags")
                    )
                );
    
    // Register custom taxonomy
    register_taxonomy(  "pcategory", 
                array(  "products"  ), 
                array ( "hierarchical"      => true, 
                        "label"             => CUSTOM_MENU_CAT_LABEL, 
                        'labels'            => array(   'name'              =>  CUSTOM_MENU_CAT_TITLE,
                                                        'singular_name'     =>  CUSTOM_MENU_SIGULAR_CAT,
                                                        'search_items'      =>  CUSTOM_MENU_CAT_SEARCH,
                                                        'popular_items'     =>  CUSTOM_MENU_CAT_SEARCH,
                                                        'all_items'         =>  CUSTOM_MENU_CAT_ALL,
                                                        'parent_item'       =>  CUSTOM_MENU_CAT_PARENT,
                                                        'parent_item_colon' =>  CUSTOM_MENU_CAT_PARENT_COL,
                                                        'edit_item'         =>  CUSTOM_MENU_CAT_EDIT,
                                                        'update_item'       =>  CUSTOM_MENU_CAT_UPDATE,
                                                        'add_new_item'      =>  CUSTOM_MENU_CAT_ADDNEW,
                                                        'new_item_name'     =>  CUSTOM_MENU_CAT_NEW_NAME,   ), 
                        'public'            => true,
                        'show_ui'           => true,
                        "rewrite"           => array('slug' => 'product','with_front' => true,'hierarchical'=>true))
                ); 
    

    My functions.php includes:

    add_filter('rewrite_rules_array', 'mmp_rewrite_rules');
    function mmp_rewrite_rules($rules) {
    $newRules  = array();
    $newRules['product/(.+)/(.+)/(.+)/(.+)/?$'] = 'index.php?products=$matches[4]';
    $newRules['product/(.+)/?$']                = 'index.php?pcategory=$matches[1]'; 
    
    return array_merge($newRules, $rules);
    }
    function filter_post_type_link($link, $post)
    {
    if ($post->post_type != 'products')
        return $link;
    
    if ($cats = get_the_terms($post->ID, 'pcategory'))
    {
        $link = str_replace('%taxonomy_name%', get_taxonomy_parents(array_pop($cats)->term_id, 'pcategory', false, '/', true), $link);
    }
    return $link;
    }
    add_filter('post_type_link', 'filter_post_type_link', 10, 2);
    
    // my own function to do what get_category_parents does for other taxonomies
    function get_taxonomy_parents($id, $taxonomy, $link = false, $nicename = false, $visited = array()) {    
    // removed $seperator="/" after $link, otherwise there was a double slash before the post name in the link    
    $chain = '';   
    $parent = &get_term($id, $taxonomy);
    
    if (is_wp_error($parent)) {
        return $parent;
    }
    
    if ($nicename)    
        $name = $parent -> slug;        
    else    
        $name = $parent -> name;
    
    if ($parent -> parent && ($parent -> parent != $parent -> term_id) && !in_array($parent -> parent, $visited)) {    
        $visited[] = $parent -> parent;    
        $chain .= get_taxonomy_parents($parent -> parent, $taxonomy, $link, $nicename, $visited); //removed $seperator after $link
        $chain .= "/"; //add a / after every category
    }
    
    if ($link) {
        // nothing, can't get this working :(
    } else    
        $chain .= $name; //don't need the . $separator anymore
    return $chain;    
    }
    
  4. maybe, that post has the parent postID(check their parent post ID’s). I doubt,their parent post doesnt exist, and when wordpress tries to get the permalink (with included slugname of its parent),then it adds only the empty slash.