2

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 2

4

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;
}
0

I used this very helpful answer for WooCommerce Product Vendors, as I wanted the Vendor in the Permalink. Below is a modified condensed snippet to do just that in your functions.php file.

//VENDOR PERMALINK
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 = 'vendor';
      $terms = wp_get_post_terms( $post->ID, 'wcpv_product_vendors' );
      if ( ! empty( $terms ) && ! is_wp_error( $terms ) )
          $term = current( $terms )->slug;
      else
          $term = $default_term;
      $permalink = str_replace( '%wcpv_product_vendors%', $term, $permalink );
    }
    return $permalink;
}
function wpse_56769_rewrite_verbose_page_rules( $pass_through = NULL ) {
    $permastruct = $GLOBALS[ 'wp_rewrite' ]->permalink_structure;
    $permastruct = trim( $permastruct, '/%' );
    if ( 0 !== strpos( $permastruct, 'wcpv_product_vendors%' ) )
        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 );
function wpse_56769_request_vars( $request_vars ) {
    if ( ! isset( $request_vars[ 'wcpv_product_vendors' ] ) )
        return $request_vars;
    if ( ! isset( $request_vars[ 'name' ] ) )
        return $request_vars;
    if ( 'no_item' == $request_vars[ 'wcpv_product_vendors' ] )
        unset( $request_vars[ 'wcpv_product_vendors' ] );
    return $request_vars;
}
add_filter( 'request', 'wpse_56769_request_vars' );

Then you would put the tag %wcpv_product_vendors% in the permalinks settings where you want it.

Thanks to the OP @INT for the very helpful answer and doing all the leg work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.