I really need your help in solving my problem.
I am trying to customize a Wordpress menu using Walker.
My task is to find out at level 0 if level 2 exists. If level 2 exists, then I need to add a unique class.
The only thing I was able to find out is whether level 1 exists with help $args->walker->has_children.
<ul>
<li> <!-- lvl 0, I'm here -->
<a></a>
<ul>
<li> <!-- lvl 1 -->
<a></a>
<ul>
<li> <!-- lvl 2, I need to find out if there are elements here -->
<a></a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
I want to supplement my question with Walker code. I am trying to add a class on <h4>
. Now the condition is working: "If this is level 0, there is a child level 1 inside, then a class is added".
/**
* Starts the element output.
*
* @since 3.0.0
* @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added.
*
* @see Walker::start_el()
*
* @param string $output Used to append additional content (passed by reference).
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $id Current item ID.
*/
public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
/**
* Filters the arguments for a single nav menu item.
*
* @since 4.4.0
*
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
*/
$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
$item_classes = '';
if($depth == 0){
if(in_array('menu-item-has-children', $item->classes)){ $item_classes = ' class="page-footer__item"';}
}
$output .= $indent . '<li' . $item_classes . '>';
$atts = array();
$atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
if ( '_blank' === $item->target && empty( $item->xfn ) ) {
$atts['rel'] = 'noopener';
} else {
$atts['rel'] = $item->xfn;
}
$atts['href'] = ! empty( $item->url ) ? $item->url : '';
$atts['aria-current'] = $item->current ? 'page' : '';
/**
* Filters the HTML attributes applied to a menu item's anchor element.
*
* @since 3.6.0
* @since 4.1.0 The `$depth` parameter was added.
*
* @param array $atts {
* The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
*
* @type string $title Title attribute.
* @type string $target Target attribute.
* @type string $rel The rel attribute.
* @type string $href The href attribute.
* @type string $aria_current The aria-current attribute.
* }
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( is_scalar( $value ) && '' !== $value && false !== $value ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
/** This filter is documented in wp-includes/post-template.php */
$title = apply_filters( 'the_title', $item->title, $item->ID );
/**
* Filters a menu item's title.
*
* @since 4.4.0
*
* @param string $title The menu item's title.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
$item_output = $args->before;
if($depth == 0){
if($args->walker->has_children){
$item_output .= '<h4 class="page-footer__list-title">'. $title .'</h4>';
}
}
elseif ($depth == 1 && $args->walker->has_children){
$item_output .= '<h4 class="page-footer__list-title ">'. $title .'</h4>';
}
else{
$item_output .= '<a' . $attributes . ' class="page-footer__link" title="'. $title .'">';
$item_output .= $args->link_before . $title . $args->link_after;
$item_output .= '</a>';
}
$item_output .= $args->after;
/**
* Filters a menu item's starting output.
*
* The menu item's starting output only includes `$args->before`, the opening `<a>`,
* the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
* no filter for modifying the opening and closing `<li>` for a menu item.
*
* @since 3.0.0
*
* @param string $item_output The menu item's starting HTML output.
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*/
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
Here you can use the basic methodology behind the concept of the walker class. As your task is to add the unique class if there is any second level of hierarchy/inheritance or depth==2, so try this code to your snippet accordingly. This simply will help to get the depth of the tree and if any level 2 exists then you would be able to add elements and that unique class..
//This function is responsible for adding "my-parent-item" class to parent menu item's
function add_menu_parent_class( $items ) {
$parents = array();
foreach ( $items as $item ) {
//Check if the item is a parent item
if ( $item->menu_item_parent && $item->menu_item_parent > 0 ) {
$parents[] = $item->menu_item_parent;
}
}
foreach ( $items as $item ) {
if ( in_array( $item->ID, $parents ) ) {
//Add "menu-parent-item" class to parents
$item->classes[] = 'my-parent-item';
}
}
return $items;
}
//add_menu_parent_class to menu
add_filter( 'wp_nav_menu_objects', 'add_menu_parent_class' );
Or You can also publish it using jQuery if you are by any chance fond of it..
$('ul li.menu-parent-item:has(ul ul)').addClass('your class');