Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gerbenvandijk/5253921 to your computer and use it in GitHub Desktop.
Save gerbenvandijk/5253921 to your computer and use it in GitHub Desktop.
Mark (highlight) custom post type parent as active item in Wordpress Navigation.When you visit a custom post type's single page, the parent menu item (the post type archive) isn't marked as active. This code solves it by comparing the slug of the current post type with the navigation items, and adds a class accordingly.
<?php
function add_current_nav_class($classes, $item) {
// Getting the current post details
global $post;
// Get post ID, if nothing found set to NULL
$id = ( isset( $post->ID ) ? get_the_ID() : NULL );
// Checking if post ID exist...
if (isset( $id )){
// Getting the post type of the current post
$current_post_type = get_post_type_object(get_post_type($post->ID));
// Getting the rewrite slug containing the post type's ancestors
$ancestor_slug = $current_post_type->rewrite ? $current_post_type->rewrite['slug'] : '';
// Split the slug into an array of ancestors and then slice off the direct parent.
$ancestors = explode('/',$ancestor_slug);
$parent = array_pop($ancestors);
// Getting the URL of the menu item
$menu_slug = strtolower(trim($item->url));
// Remove domain from menu slug
$menu_slug = str_replace($_SERVER['SERVER_NAME'], "", $menu_slug);
// If the menu item URL contains the post type's parent
if (!empty($menu_slug) && !empty($parent) && strpos($menu_slug,$parent) !== false) {
$classes[] = 'current-menu-item';
}
// If the menu item URL contains any of the post type's ancestors
foreach ( $ancestors as $ancestor ) {
if (!empty($menu_slug) && !empty($ancestor) && strpos($menu_slug,$ancestor) !== false) {
$classes[] = 'current-page-ancestor';
}
}
}
// Return the corrected set of classes to be added to the menu item
return $classes;
}
add_action('nav_menu_css_class', 'add_current_nav_class', 10, 2 );
@jhtjards
Copy link

jhtjards commented Feb 8, 2021

Great Gist, thanks to everyone for sharing! Saved me a lot of time!

It did however not work for me with child pages that are an ancestor of a menu item.
I think it's because pages don't have a rewrite slug.

So I checked for pages and populated the ancestors array accordingly

if ( $current_post_type->name == 'page'){
	$ancestors = array();
	foreach ( get_post_ancestors($post) as $ancestor ) {
		$ancestors[] = get_post_field( 'post_name', $ancestor );
	}
}

This is the full snippet:

function add_current_nav_class($classes, $item) {

	// Getting the current post details
	global $post;

	// Get post ID, if nothing found set to NULL
	$id = ( isset( $post->ID ) ? get_the_ID() : NULL );

	// Checking if post ID exist...
	if (isset( $id )){

		// Getting the post type of the current post
		$current_post_type = get_post_type_object(get_post_type($post->ID));
		//var_dump($current_post_type->name);

		// Getting the rewrite slug containing the post type's ancestors
		$ancestor_slug = $current_post_type->rewrite ? $current_post_type->rewrite['slug'] : '';

		// Split the slug into an array of ancestors and then slice off the direct parent.
		$ancestors = explode('/',$ancestor_slug);

		// Pages have no rewrite base, so check for parent pages and populate array with all slugs of parents
		if ( $current_post_type->name == 'page'){
			$ancestors = array();
			foreach ( get_post_ancestors($post) as $ancestor ) {
				$ancestors[] = get_post_field( 'post_name', $ancestor );
			}
		}

		$parent = array_pop($ancestors);

		// Getting the URL of the menu item
		$menu_slug = strtolower(trim($item->url));

		// Remove domain from menu slug
		$menu_slug = str_replace($_SERVER['SERVER_NAME'], "", $menu_slug);

		// If the menu item URL contains the post type's parent
		if (!empty($menu_slug) && !empty($parent) && strpos($menu_slug,$parent) !== false) {
			$classes[] = 'current-menu-item';
		}

		// If the menu item URL contains any of the post type's ancestors
		foreach ( $ancestors as $ancestor ) {
			if (!empty($menu_slug) && !empty($ancestor) && strpos($menu_slug,$ancestor) !== false) {
				$classes[] = 'current-page-ancestor';
			}
		}
	}
	// Return the corrected set of classes to be added to the menu item
	return $classes;
}
add_action('nav_menu_css_class', 'add_current_nav_class', 10, 2 );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment