WordPress Conditonal Menus

I had a need to add a login button on the top right side of my menu system in WordPress:

Login

Seemed easy enough, just go to Appearance | Menus from your Dashboard and add a Custom Link that points to https://www.dforge.net/wp-login.php. Then play around with the CSS for that element using CSS selectors so that it floats to the right side:

li.login {
  float: right;
}

Note that you can add a CSS class to your menu items by making sure that option is selected in the Screen Options area; in my case, I used “login” as my CSS class. Unfortunately, that wasn’t the end of it because after you login, the menu item still remains as “Login” and not “Logout”. Duh.

So, I needed some form of conditional menu in WordPress. According to this article, you can create a custom walker that will “walk” through your menu items. As you “walk”, or iterate, through your menu items, you can decide to change various properties of that menu item. In my case, I wanted to change the title property from “Login” to “Logout” and the URL from “https://www.dforge.net/wp-login.php” to “https://www.dforge.net/wp-login.php?action=logout“, but only do this to the appropriate menu item.

There will be essentially two files you’ll need to edit: functions.php and header.php.

SIDE NOTE: If you’re using a WordPress theme and haven’t already done so, make a child theme from your main theme so you can edit your child theme at will (see http://codex.wordpress.org/Child_Themes). Once you’ve created your child theme, you can then copy the functions.php and header.php files from the main theme folder to your new child theme folder.

Here’s a breakdown of what each file should contain:

functions.php – will contain the code that will walk through your menu items and modify the properties that you need to modify (notable code is in red):

class description_walker extends Walker_Nav_Menu {
  function start_el(&$output, $item, $depth, $args) {
    global $wp_query;
    $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';
    $class_names = $value = '';
    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
    $class_names = '';
    $output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
    $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
    $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
    $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
    $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( ($item->title == "Login" && is_user_logged_in() ? wp_logout_url() : $item->url)        ) .'"' : '';
    $prepend = '<strong>';
    $append = '</strong>';
    $description  = ! empty( $item->description ) ? '<span>'.esc_attr( $item->description ).'</span>' : '';

    if($depth != 0) {
      $description = $append = $prepend = "";
    }

    $item_output = $args->before;
    $item_output .= '<a'. $attributes .'>';
    $item_output .= $args->link_before .$prepend.apply_filters( 'the_title', ($item->title == "Login" && is_user_logged_in() ? "Logout" : $item->title), $item->ID ).$append;
    $item_output .= $description.$args->link_after;
    $item_output .= '</a>';
    $item_output .= $args->after;

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
  }
}

header.php – has the code that calls the wp_nav_menu function you will need to edit. The wp_nav_menu function is the function that generates your menu and takes in a parameter that is an array of options, one of which is called walker that will point your code in the functions.php file (notable code is in red)

wp_nav_menu(
  array(
    'container'       => '',
    'theme_location'  => 'header-menu',
    'walker' => new description_walker()
  )
);