Tiffin Consulting

digital business transformation

WordPress log in / log out menus

One of the downsides of WordPress menus is the inability to have a set of menus for logged-in users that may differ from the primary menu.

Many sites tackle this in various ways, but a conventional approach is to have a separate menus to handle  the logged-in and logged-out states of the visitor.

A menu for logged-in users and one for logged-out

primary menu

Here is a screen shot of the secondary menu for the logged-out visitor (ie public view).

logout-menu

As you can see the menu appears above the main menu and consist of a registration and login link.  This menu needs to change when the user is actually logged in…

log in menu

In the above case, the site is conference registration site and the menu changes to a Submission and logout menu.

Integration with the WordPress Menu Manager

Now here comes the beautiful part of this custom menu….

wp menu manager - logout

As you can see from the above screenshot of the site Dashboard, the menu manager allows the webmaster to configure the logged-out menu by adding other pages, sub-menus, links, post, categories and what not.  However, the only thing missing is the Login menu link.  This is done dynamically with a function by simply adding a login menu item at the end of the menu structure.

wp menu manager-login

Same thing for the logged-in menu structure, no login menu item.

So what’s the big deal?

Why did we do this?  Well for starters, adding logout/login urls has to be done manually using the custom Links items, which means that if the the site domain name changes (such going from a demo to a live site) one needs to remember to change it.  However, we also wanted to add an Ajax-enabled login functionality as described in this neat little tutorial by Natko Hasik.  And the result is this:

ajax-login

Neat no?

So how does it work?  Well here is the magic….

The functions.php file first

Here is the code to register the two menus that we will be using in the headers of our site…

function sy_conf_register_menu() {
  register_nav_menu('quick-in-menu',__( 'Quick Loged-in Menu' ));
  register_nav_menu('quick-out-menu',__( 'Quick Loged-out Menu' ));
}
add_action( 'init', 'sy_conf_register_menu' ); // register additional menu

Next is the function which will add the necessary login and logout menu links dynamically each time the menus are being called by the header…

function sy_quick_nav_items( $items, $args ) 
{ //$items, $menu,
    if( 'quick-in-menu' == $args->theme_location )
        $items.= '<li><a href="'.wp_logout_url(get_permalink()).'" title="Logout">Logout</a></li>';
     if( 'quick-out-menu' == $args->theme_location ) {
           $logInitem = '<a id="show_login" href="">Login</a>';
        $logInitem.= '<form id="login" action="login" method="post">';
        $logInitem.= '    <p></p>';
        $logInitem.= '    <div id="loginFields"><p><label for="username">Username</label><input id="username" type="text" name="username"></p>';
        $logInitem.= '    <p><label for="password">Password</label><input id="password" type="password" name="password"></p>';
        $logInitem.= '    <p id="lostPass"><a href="<?php echo wp_lostpassword_url(); ?>">Lost your password?</a></p>';
        $logInitem.= '    <p id="loginButton"><a href="javascript:void(0)">Cancel</a><input type="submit" value="Login" name="submit"></p></div>';
        $logInitem.= wp_nonce_field( 'ajax-login-nonce', 'security' );
        $logInitem.= '</form>';
        $items.= $logInitem;
    }
    return $items;
}
add_filter( 'wp_nav_menu_items','sy_quick_nav_items', 10, 2 );

Finally the Ajax initialisation …

function ajax_login_init(){
    wp_register_script('ajax-login-script', get_stylesheet_directory_uri() . '/js/ajax-login-script.js', array('jquery') ); 
    wp_enqueue_script('ajax-login-script');
    wp_localize_script( 'ajax-login-script', 'ajax_login_object', array( 
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
        'redirecturl' => home_url(),
        'loadingmessage' => __('Logging in, please wait...')
    ));
    // Enable the user with no privileges to run ajax_login() in AJAX
    add_action( 'wp_ajax_nopriv_ajaxlogin', 'ajax_login' );
}
// Execute the action only if the user isn't logged in
if (!is_user_logged_in()) {
    add_action('init', 'ajax_login_init');
}

…and call handlers…

function ajax_login(){
    // First check the nonce, if it fails the function will break
    check_ajax_referer( 'ajax-login-nonce', 'security' );
    // Nonce is checked, get the POST data and sign user on
    $info = array();
    $info['user_login'] = $_POST['username'];
    $info['user_password'] = $_POST['password'];
    $info['remember'] = true;
    $user_signon = wp_signon( $info, false );
    if ( is_wp_error($user_signon) ){
        echo json_encode(array('loggedin'=>false, 'message'=>__('Wrong username or password.')));
    } else {
        echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...')));
    }
    die();
}
Ajax Javascript file ajax-login-script.js

This is the javascript file that will be loaded, I place it in the js/ folder of my child-theme root folder…save the code into a new file called ajax-login-script.js

jQuery(document).ready(function($) {
    // Show the login dialog box on click
    $('a#show_login').on('click', function(e){
        $('body').prepend('<div></div>');
        $('form#login').fadeIn(500);
        $('div.login_overlay, form#login a.close').on('click', function(){
            $('div.login_overlay').remove();
            $('form#login').hide();
        });
        e.preventDefault();
    });
    // Perform AJAX login on form submit
    $('form#login').on('submit', function(e){
        $('form#login div#loginFields').fadeOut(500);
        $('form#login p.status').show().text(ajax_login_object.loadingmessage);
        $.ajax({
            type: 'POST',
            dataType: 'json',
            url: ajax_login_object.ajaxurl,
            data: { 
                'action': 'ajaxlogin', //calls wp_ajax_nopriv_ajaxlogin
                'username': $('form#login #username').val(), 
                'password': $('form#login #password').val(), 
                'security': $('form#login #security').val() },
            success: function(data){
                $('form#login p.status').text(data.message);
                if (data.loggedin == true){
                    document.location.href = ajax_login_object.redirecturl;
                }
            }
        });
        e.preventDefault();
    });
});
CSS beautification….

the css needed to make it all look good…

form#login {
    background-color: #FFFFFF;
    border-top: 3px solid #7B0099;
    display: none;
    padding: 5px;
    position: fixed;
    z-index: 999;
}
#login div#loginFields > p {
    line-height: 0.5em;
    padding-bottom: 5px;
    text-align: right;
}
#login div#loginFields > p#lostPass {
    text-align: center;
}
#login div#loginFields input {
    border: 1px solid #D3D3D3;
    padding: 1px 2px;
    width: 100px;
}
#login div#loginFields label {
    margin-right: 5px;
}

form#login p.status{
    display: none;
    line-height: 0.5em;
    padding-bottom: 5px;
    text-align: center;
}
form#login div#loginFields a.close {
    background: none repeat scroll 0 0 #F0F0F0;
    border: 1px solid #D3D3D3;
    color: #00266A;
    font-size: 11px;
    margin-right: 4px;
    padding: 1px 25px;
}
#login div#loginFields input.submit_button {
    color: #00266A;
    padding: 0 2px;
    width: 86px;
}
.login_overlay{
    height: 100%;
    width: 100%;
    background-color: transparent;
    opacity: 0.9;
    position: fixed;
    z-index: 998;
}
Integration into the header…

This is the tricky part, because the header will differ from one theme to the next and you will need to see where best to fit in your additional menus…

<body>
    <header>
         <div id="top-navigation">
                <nav id="quick-nav">
                <?php
                    $menuClass = 'nav';
            if ( is_user_logged_in() ) {
                //get the logged-out menu 
                $quickNav = wp_nav_menu( array( 'theme_location' => 'quick-in-menu', 'container' => '', 'fallback_cb' => '', 'menu_class' => $menuClass, 'menu_id' => 'quick-menu', 'echo' => false ) );
                if ( '' == $quickNav ) : //in case the menus have not been setup
                ?>
                    <ul id="quick-menu">
                        <li><a href="<?php echo wp_logout_url(get_permalink()); ?>" title="Logout">Logout</a></li>
                    </ul>
                <?php
                else :
                    echo ( $quickNav );
                endif;
            } else {
                //get the logged-in menu
                $quickNav = wp_nav_menu( array( 'theme_location' => 'quick-out-menu', 'container' => '', 'fallback_cb' => '', 'menu_class' => $menuClass, 'menu_id' => 'quick-menu', 'echo' => false ) );
                if ( '' == $quickNav ) ://in case the menus have not been setup
            ?>
                    <ul id="quick-menu">
                        <li><a href="<?php echo wp_login_url(get_permalink()); ?>" title="Login">Login</a></li>
                    </ul>
            <?php
                else :
                    echo ( $quickNav );
                endif;
            }
            ?>
                </nav>
                <nav id="top-menu">
                <?php
                    $menuClass = 'nav';
                            $primaryNav = wp_nav_menu( array( 'theme_location' => 'primary-menu', 'container' => '', 'fallback_cb' => '', 'menu_class' => $menuClass, 'menu_id' => 'top-menu', 'echo' => false ) );
                                 ?>
                                <!-- ...your primary menu html code....-->
                </nav>
         </div>
    </header>

Comments

3 responses to “WordPress log in / log out menus”

  1. […] good tutorials to build custom menus for logged in/logged out users, see also our own post on the ajax login menu.  There are more complex approaches in order to customise the individual menu items using a the […]

  2. esl activities Avatar
    esl activities

    Great blog here! Also your website loads up fast! What web
    host are you using? Can I get your affiliate link to your host?
    I wish my site loaded up as fast as ypurs lol

    1. Webguruji Avatar
      Webguruji

      We use GreenGeeks.com, a link is provided in our footer…