I’ve created a custom taxonomy for the product post type created by WooCommerce. I want to use this taxonomy to the permalinks of the products.
I stumbled upon this which seemed to be perfect for what I wanted to do.
However, I’m having little luck getting it to work. Adding the code in the post I still end up with %item% (which I’m using, rather than %artist%) rather than the term in my permalink.
<?php
/*
Plugin Name: Woocommerce Item Taxonomy
Description: Enables a Taxonomy called "Item" for organizing multiple single products under an unified item.
Version: 1.0.0
License: MIT License
*/
add_action( 'init', 'ps_taxonomy_item' );
function ps_taxonomy_item() {
$labels = array(
'name' => 'Item',
'singular_name' => 'Item',
'menu_name' => 'Item',
'all_items' => 'All Items',
'parent_item' => 'Parent Item',
'parent_item_colon' => 'Parent Item:',
'new_item_name' => 'New Item Name',
'add_new_item' => 'Add New Item',
'edit_item' => 'Edit Item',
'update_item' => 'Update Item',
'separate_items_with_commas' => 'Separate Item with commas',
'search_items' => 'Search Items',
'add_or_remove_items' => 'Add or remove Items',
'choose_from_most_used' => 'Choose from the most used Items',
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => true,
'show_in_nav_menus' => true,
'show_tagcloud' => true,
);
register_taxonomy( 'item', 'product', $args );
register_taxonomy_for_object_type( 'item', 'product' );
}
/**
* replace the '%item%' tag with the first
* term slug in the item taxonomy
*
* @wp-hook post_link
* @param string $permalink
* @param WP_Post $post
* @return string
*/
add_filter( 'post_link', 'wpse_56769_post_link', 10, 2 );
function wpse_56769_post_link( $permalink, $post ) {
$default_term = 'no_item';
$terms = wp_get_post_terms( $post->ID, 'item' );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) )
$term = current( $terms )->slug;
else
$term = $default_term;
$permalink = str_replace( '%item%', $term, $permalink );
return $permalink;
}
/**
* set WP_Rewrite::use_verbose_page_rules to TRUE if %item%
* is used as the first rewrite tag in post permalinks
*
* @wp-hook do_parse_request
* @wp-hook page_rewrite_rules
* @global $wp_rewrite
* @param mixed $pass_through (Unused)
* @return mixed
*/
function wpse_56769_rewrite_verbose_page_rules( $pass_through = NULL ) {
$permastruct = $GLOBALS[ 'wp_rewrite' ]->permalink_structure;
$permastruct = trim( $permastruct, '/%' );
if ( 0 !== strpos( $permastruct, 'item%' ) )
return $pass_through;
$GLOBALS[ 'wp_rewrite' ]->use_verbose_page_rules = TRUE;
return $pass_through;
}
add_filter( 'page_rewrite_rules', 'wpse_56769_rewrite_verbose_page_rules', PHP_INT_MAX );
add_filter( 'do_parse_request', 'wpse_56769_rewrite_verbose_page_rules', PHP_INT_MAX );
/**
* check for existing item and set query to 404 if necessary
*
* @wp-hook parse_query
* @param array $request_vars
* @return array
*/
function wpse_56769_request_vars( $request_vars ) {
if ( ! isset( $request_vars[ 'item' ] ) )
return $request_vars;
if ( ! isset( $request_vars[ 'name' ] ) )
return $request_vars;
if ( 'no_item' == $request_vars[ 'item' ] )
unset( $request_vars[ 'item' ] );
return $request_vars;
}
add_filter( 'request', 'wpse_56769_request_vars' );
2 Answers
As always it was too simple in the end, was using the wrong hook. post_link
is for posts only should use post_type_link
instead.
/**
* replace the '%item%' tag with the first
* term slug in the item taxonomy
*
* @wp-hook post_link
* @param string $permalink
* @param WP_Post $post
* @return string
*/
add_filter( 'post_type_link', 'wpse_56769_post_link', 10, 2 );
function wpse_56769_post_link( $permalink, $post ) {
if( $post->post_type == 'product' ) {
$default_term = 'no_item';
$terms = wp_get_post_terms( $post->ID, 'item' );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) )
$term = current( $terms )->slug;
else
$term = $default_term;
$permalink = str_replace( '%item%', $term, $permalink );
}
return $permalink;
}