wp_nav_menu() loses 'current-menu-*' classes on single product page within category

I have my menu set up like so:

  • Shop Online (WPeC ‘Products Page’ page)
    • Product Category (WPeC Category)
    • Product Category (WPeC Category)
      • Product Sub Category (WPeC Category)
      • Product Sub Category (WPeC Category)

Single product pages are viewable from any category or sub category page as they both show the product listing view.

Now when I select either Shop Online, a product category or sub-category the menu updates it’s CSS classes to match the current hierachy with the usual (example) current-menu-page, current-menu-ancestor and current-menu-parent among others. It doesn’t matter if I click on the menu or the category listing on the Shop Online page to get there.

For some reason as soon as I view a product singularly (domain.tld/product-cat/sub-cat/product-single or domain.tld/product-cat/product-single), the menu classes are removed and I lose my menu highlighting because the classes are no longer there.

Is there a way that I can reflect the single product view in the menu by highlighting the current category/ies that the product is in, as well as the Shop Online menu item/link respective of how you got to the product?

WP v3.5

WPeC v3.8.9.4

Solutions Collecting From Web of "wp_nav_menu() loses 'current-menu-*' classes on single product page within category"

Looking for a solution for the same problem, I came across this:

add_filter( 'nav_menu_css_class', 'add_parent_url_menu_class', 10, 2 );

function add_parent_url_menu_class( $classes = array(), $item = false ) {
    // Get current URL
    $current_url = current_url();

    // Get homepage URL
    $homepage_url = trailingslashit( get_bloginfo( 'url' ) );

    // Exclude 404 and homepage
    if( is_404() or $item->url == $homepage_url ) return $classes;

    if ( strstr( $current_url, $item->url) ) {
        // Add the 'parent_url' class
        $classes[] = 'parent_url';
    }

    return $classes;
}

function current_url() {
    // Protocol
    $url = ( 'on' == $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
    $url .= $_SERVER['SERVER_NAME'];

    // Port
    $url .= ( '80' == $_SERVER['SERVER_PORT'] ) ? '' : ':' . $_SERVER['SERVER_PORT'];
    $url .= $_SERVER['REQUEST_URI'];
    return trailingslashit( $url );
}

Code from: http://www.rarescosma.com/2010/11/add-a-class-to-wp_nav_menu-items-with-urls-included-in-the-current-url/

Hope it helps!

If you are using Woocommerce plugin you can add class like this

    if (
        ($post->post_type == 'product') &&
        ($item->object_id == get_option('woocommerce_shop_page_id'))
    ) {
        array_push($classes, 'current-page-ancestor');
    }

How To Get WooCommerce Page IDs

get_option( 'woocommerce_shop_page_id' ); 
get_option( 'woocommerce_cart_page_id' ); 
get_option( 'woocommerce_checkout_page_id' );
get_option( 'woocommerce_pay_page_id' ); 
get_option( 'woocommerce_thanks_page_id' ); 
get_option( 'woocommerce_myaccount_page_id' ); 
get_option( 'woocommerce_edit_address_page_id' ); 
get_option( 'woocommerce_view_order_page_id' ); 
get_option( 'woocommerce_terms_page_id' ); 

As explained by a support tech over at getshopped.org:

[sic] is actually a limitation of the WordPress menu system. I am
unaware of a way to change this behavior. Possibly you could find a
menu plugin and make your menu area a widget where you could add the
menu by widget that provides an enhanced menu system.