Ultimate guide on redirect to custom page after login / register fails

It’s quite easy to setup a frontend registration or login form. You can find a really extensive ammount of tutorials on this topic. And usually everything works great – your users do not see typical WordPress login/register page and are redirected to frontend of your website. Till either registration or login fails. Than most of solutions fails too – users are not redirected and see typical WordPress login/register screen. What now? It’s quite hard to find a solution on the internet – that’s why I’ve prepared this ultimate howto.

Actually, to redirect after login fails is well documented – there is a special hook for that in WordPress. You can find a great tutorials on this.

So in breaf: here’s my code based on this solution: How to Redirect WordPress Failed Logins (modified as original code stackups login=fail attrs):

// hook failed login
add_action('wp_login_failed', 'my_frontend_login_fail'); 
 
function my_frontend_login_fail($username){
    // Get the reffering page, where did the post submission come from?
    $referrer = add_query_arg('login', false, $_SERVER['HTTP_REFERER']);
 
    // if there's a valid referrer, and it's not the default log-in screen
    if(!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin')){
        // let's append some information (login=failed) to the URL for the theme to use
        wp_redirect($referrer . '?login=failed'); 
    exit;
    }
}

Ok, this was easy, wasn’t it? But wait! What has happen when a user submit your custom login form (frontend login form) empty? He/She will land on wp-login.php again instead on your custom login form. To fix this behaviour, add this code also:

add_action( 'login_head', 'my_frontend_login_no_pass_no_username' );

function my_frontend_login_no_pass_no_username(){
    $referrer = add_query_arg('login', false, $_SERVER['HTTP_REFERER']);
    if ( (!isset($_REQUEST['user_login']) || ( isset( $_REQUEST['user_login'] ) && trim( $_REQUEST['user_login'] ) == '' ) ) || (!isset($_REQUEST['user_pass']) || ( isset( $_REQUEST['user_pass'] ) && trim( $_REQUEST['user_pass'] ) == '' ) ) ){
        wp_redirect( add_query_arg('login', 'failed', $referrer) ); 
        exit; 
    }   
}

And now, what if we would like to redirect our user (not registered yet) to a custom page after unsuccessful registration attempt?

Have to say, that I’v originally published this solution, with extensive comment, on WordPress Answers – vote up, if you find this solution helpful, thx.

Again in breaf, here’s the code:

add_action('register_post', 'binda_register_fail_redirect', 99, 3);

function binda_register_fail_redirect( $sanitized_user_login, $user_email, $errors ){
    //this line is copied from register_new_user function of wp-login.php
    $errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );
    //this if check is copied from register_new_user function of wp-login.php
    if ( $errors->get_error_code() ){
        //setup your custom URL for redirection
        $redirect_url = get_bloginfo('url') . '/registrace';
        //add error codes to custom redirection URL one by one
        foreach ( $errors->errors as $e => $m ){
            $redirect_url = add_query_arg( $e, '1', $redirect_url );    
        }
        //add finally, redirect to your custom page with all errors in attributes
        wp_redirect( $redirect_url );
        exit;   
    }
}

Čeština pro WordPress 3.5.1

Před několika dny vyšla první opravná a bezpečnostní verze WordPress 3.5.1. Čeština vychází teprve dnes (chřipka) a obsahuje pouze několik drobných změn. Doporučujeme neotálet s automatickou aktualizací, pro nové instalace si pak můžete stáhnout kompletní balíček. A pro zajímavost, zatím byla česká verze WordPressu 3.5 použita na téměř 14 tisíc webech. Aktuální česká verze by se […]

No hierarchy of pages when adding pages to nav menus with too many pages

WordPress had problems with hierarchy on Menu page in history. There was no hierarchy at all for pages on View All tab. Now, it is fixed. At first glance. When you have more than 50 pages, you’ll run into problem.

Your pages will be divided to two or more pages. The first page is OK, second and next not. On second and next page, there are pages without hierarchy. This makes it almost imposible to setup a nav menu.

I have a quick fix for this issue. It will remove the mentioned pagination and will display reall „All“ pages on single tab. Copy and paste the following WordPress snippet to your functions.php.

function binda_modify_nav_menu_items_page( $posts, $args, $post_type ){
	global $_nav_menu_placeholder, $nav_menu_selected_id;

	$post_type_name = $post_type['args']->name;

	$args = array(
		'offset' => $offset,
		'order' => 'ASC',
		'orderby' => 'title',
		'posts_per_page' => -1,
		'post_type' => $post_type_name,
		'suppress_filters' => true,
		'update_post_term_cache' => false,
		'update_post_meta_cache' => false
	);

	if ( isset( $post_type['args']->_default_query ) )
		$args = array_merge($args, (array) $post_type['args']->_default_query );

	$get_posts = new WP_Query;
	$posts = $get_posts->query( $args );

	if ( !$posts )
		$error = '
  • '. $post_type['args']->labels->not_found .'
  • '; // if we're dealing with pages, let's put a checkbox for the front page at the top of the list if ( 'page' == $post_type_name ) { $front_page = 'page' == get_option('show_on_front') ? (int) get_option( 'page_on_front' ) : 0; if ( ! empty( $front_page ) ) { $front_page_obj = get_post( $front_page ); $front_page_obj->front_or_home = true; array_unshift( $posts, $front_page_obj ); } else { $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1; array_unshift( $posts, (object) array( 'front_or_home' => true, 'ID' => 0, 'object_id' => $_nav_menu_placeholder, 'post_content' => '', 'post_excerpt' => '', 'post_parent' => '', 'post_title' => _x('Home', 'nav menu home label'), 'post_type' => 'nav_menu_item', 'type' => 'custom', 'url' => home_url('/'), ) ); } } return $posts; } add_action ( 'nav_menu_items_page', 'binda_modify_nav_menu_items_page', 1, 3 ); add_action( 'admin_print_styles-' . 'nav-menus.php', 'binda_nav_menu_custom_css' ); function binda_nav_menu_custom_css() { echo '#posttype-page .add-menu-item-pagelinks{display:none;}'; }

    No hierarchy of pages when adding pages to nav menus with too many pages

    WordPress had problems with hierarchy on Menu page in history. There was no hierarchy at all for pages on View All tab. Now, it is fixed. At first glance. When you have more than 50 pages, you’ll run into problem.

    Your pages will be divided to two or more pages. The first page is OK, second and next not. On second and next page, there are pages without hierarchy. This makes it almost imposible to setup a nav menu.

    I have a quick fix for this issue. It will remove the mentioned pagination and will display reall „All“ pages on single tab. Copy and paste the following WordPress snippet to your functions.php.

    function binda_modify_nav_menu_items_page( $posts, $args, $post_type ){
    	global $_nav_menu_placeholder, $nav_menu_selected_id;
    
    	$post_type_name = $post_type['args']->name;
    
    	$args = array(
    		'offset' => $offset,
    		'order' => 'ASC',
    		'orderby' => 'title',
    		'posts_per_page' => -1,
    		'post_type' => $post_type_name,
    		'suppress_filters' => true,
    		'update_post_term_cache' => false,
    		'update_post_meta_cache' => false
    	);
    
    	if ( isset( $post_type['args']->_default_query ) )
    		$args = array_merge($args, (array) $post_type['args']->_default_query );
    
    	$get_posts = new WP_Query;
    	$posts = $get_posts->query( $args );
    
    	if ( !$posts )
    		$error = '
  • '. $post_type['args']->labels->not_found .'
  • '; // if we're dealing with pages, let's put a checkbox for the front page at the top of the list if ( 'page' == $post_type_name ) { $front_page = 'page' == get_option('show_on_front') ? (int) get_option( 'page_on_front' ) : 0; if ( ! empty( $front_page ) ) { $front_page_obj = get_post( $front_page ); $front_page_obj->front_or_home = true; array_unshift( $posts, $front_page_obj ); } else { $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1; array_unshift( $posts, (object) array( 'front_or_home' => true, 'ID' => 0, 'object_id' => $_nav_menu_placeholder, 'post_content' => '', 'post_excerpt' => '', 'post_parent' => '', 'post_title' => _x('Home', 'nav menu home label'), 'post_type' => 'nav_menu_item', 'type' => 'custom', 'url' => home_url('/'), ) ); } } return $posts; } add_action ( 'nav_menu_items_page', 'binda_modify_nav_menu_items_page', 1, 3 ); add_action( 'admin_print_styles-' . 'nav-menus.php', 'binda_nav_menu_custom_css' ); function binda_nav_menu_custom_css() { echo '#posttype-page .add-menu-item-pagelinks{display:none;}'; }

    Rozšíření šablony o editovatelná menu

    WordPress nabízí možnost využití  menu upravitelných z administrace. To je velký krok kupředu směrem k CMS. Pokud se učíte, jak tvořit šablony pro WP nebo jen máte starou šablonu a potřebovali byste ji modernizovat o tuto funkcionalitu, pomůže vám tento rychlý exkurz.

    Předně je nutné v souboru functions.php nové mezu zaregistrovat. Stačí vložit následující kód:

    if ( function_exists( 'register_nav_menus' ) ) {
    	register_nav_menus(
    		array(
    	  		'primary_menu' => 'Hlavní menu',
    	  		'foot_menu' => 'Menu v patičce'
    		)
    	);
    }

    Jistě jste si všimli, že jsme tímto příkazem zaregistovali hned dvě navigační menu. Hlavní menu a menu v patičce. Pokud byste chtěli jen jedno, odstraňte řádek „‚foot_menu‘ => ‚Menu v patičce’“, nebo naopak ukončete tento řádek čárkou a přidejte ješte jeden. Dbejte na to, že první parametr (tedy ‚foot_menu‘ a ‚primary_menu‘) musí být unikátní. Druhý slouží pro vaši orientaci, takže ideálně by měl být také unikátní, ale WordPress na tom netrvá.

    Tímto jste si zaregistrovali menu a nyní již naleznete v administraci navigačních menu (Vzhled->Menu) nalevo v boxu své dvě pozice („Hlavní menu“, „Menu v patičce“) a lze vytvářet menu a přiřazovat je těmto dvoum pozicím.

    Nyní tedy již zbývá pouze nechat zobrazit menu v šabloně. Je nutné zvolit místo, kde chcete menu zobrazit – to je na vás. Pokud modernizujete starou šablonu, budete nejspíš nahrazovat funkci „wp_list_categories“ umístěnou v souboru header.php nebo sidebar.php.

    Pro vložení menu do šablony použijte níže uvedený kód. Všechny uvedené parametry jsou parametry defaultní a proto, když je nebudete měnit, můžete je, pro zkrácení kódu, odstranit. Funkce wp_nav_menu má ještě další parametry (menu,walker,falback_cp), ale ty jsou pro začátečníka zbytečně komplikované a zřítka využitelné. Koho by zajímaly, nechť se obrází na kodex

     'primary_menu', //unikátní identifikátor menu nastavený v functions.php
      'container'       => 'div', //nebo 'nav' nebo false. Určuje, co se má použít jako element obklopující element UL samotného menu. False znamená, že žádný takový element nebude
      'container_class' => 'menu-{menu slug}-container', //třída (class) elementu UL obklopující samotné menu
      'container_id'    => '', //parametr ID elementu obklopujícího element UL samotného menu
      'menu_class'      => 'menu',  //třída (class) elementu UL obklopujcí menu
      'menu_id'         => 'nav', //parametr ID elementu UL obklopující menu
      'echo'            => true, //má se menu vypsat, nebo jen vrátit pomocí fce return?
      'before'          => '', //text před HTML tagem  'after' => '', //text za HTML tagem 'link_before'     => '', //text před samotným textem odkazu
      'link_after'      => '', //text za samotným textem odkazu
      'items_wrap'      => '
      %3$s
    ', //HTML markup vlastního menu
      'depth'           => 0, //do kolikáté úrovně zobrazovat podstránky. 0 znamená všechny úrovně
    );
    wp_nav_menu( $args ); ?>

    Rozšíření šablony o editovatelná menu

    WordPress nabízí možnost využití  menu upravitelných z administrace. To je velký krok kupředu směrem k CMS. Pokud se učíte, jak tvořit šablony pro WP nebo jen máte starou šablonu a potřebovali byste ji modernizovat o tuto funkcionalitu, pomůže vám tento rychlý exkurz.

    Předně je nutné v souboru functions.php nové mezu zaregistrovat. Stačí vložit následující kód:

    if ( function_exists( 'register_nav_menus' ) ) {
    	register_nav_menus(
    		array(
    	  		'primary_menu' => 'Hlavní menu',
    	  		'foot_menu' => 'Menu v patičce'
    		)
    	);
    }

    Jistě jste si všimli, že jsme tímto příkazem zaregistovali hned dvě navigační menu. Hlavní menu a menu v patičce. Pokud byste chtěli jen jedno, odstraňte řádek “‘foot_menu’ => ‘Menu v patičce’”, nebo naopak ukončete tento řádek čárkou a přidejte ješte jeden. Dbejte na to, že první parametr (tedy ‘foot_menu’ a ‘primary_menu’) musí být unikátní. Druhý slouží pro vaši orientaci, takže ideálně by měl být také unikátní, ale WordPress na tom netrvá.

    Tímto jste si zaregistrovali menu a nyní již naleznete v administraci navigačních menu (Vzhled->Menu) nalevo v boxu své dvě pozice (“Hlavní menu”, “Menu v patičce”) a lze vytvářet menu a přiřazovat je těmto dvoum pozicím.

    Nyní tedy již zbývá pouze nechat zobrazit menu v šabloně. Je nutné zvolit místo, kde chcete menu zobrazit – to je na vás. Pokud modernizujete starou šablonu, budete nejspíš nahrazovat funkci “wp_list_categories” umístěnou v souboru header.php nebo sidebar.php.

    Pro vložení menu do šablony použijte níže uvedený kód. Všechny uvedené parametry jsou parametry defaultní a proto, když je nebudete měnit, můžete je, pro zkrácení kódu, odstranit. Funkce wp_nav_menu má ještě další parametry (menu,walker,falback_cp), ale ty jsou pro začátečníka zbytečně komplikované a zřítka využitelné. Koho by zajímaly, nechť se obrází na kodex

    <?php $args = array(
      'theme_location'  => 'primary_menu', //unikátní identifikátor menu nastavený v functions.php
      'container'       => 'div', //nebo 'nav' nebo false. Určuje, co se má použít jako element obklopující element UL samotného menu. False znamená, že žádný takový element nebude
      'container_class' => 'menu-{menu slug}-container', //třída (class) elementu UL obklopující samotné menu
      'container_id'    => '', //parametr ID elementu obklopujícího element UL samotného menu
      'menu_class'      => 'menu',  //třída (class) elementu UL obklopujcí menu
      'menu_id'         => 'nav', //parametr ID elementu UL obklopující menu
      'echo'            => true, //má se menu vypsat, nebo jen vrátit pomocí fce return?
      'before'          => '', //text před HTML tagem <a>
      'after'           => '', //text za HTML tagem </a>
      'link_before'     => '', //text před samotným textem odkazu
      'link_after'      => '', //text za samotným textem odkazu
      'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>', //HTML markup vlastního menu
      'depth'           => 0, //do kolikáté úrovně zobrazovat podstránky. 0 znamená všechny úrovně
    );
    wp_nav_menu( $args ); ?>

    Rozšíření šablony o editovatelná menu

    WordPress nabízí možnost využití  menu upravitelných z administrace. To je velký krok kupředu směrem k CMS. Pokud se učíte, jak tvořit šablony pro WP nebo jen máte starou šablonu a potřebovali byste ji modernizovat o tuto funkcionalitu, pomůže vám tento rychlý exkurz.

    Předně je nutné v souboru functions.php nové mezu zaregistrovat. Stačí vložit následující kód:

    if ( function_exists( 'register_nav_menus' ) ) {
    	register_nav_menus(
    		array(
    	  		'primary_menu' => 'Hlavní menu',
    	  		'foot_menu' => 'Menu v patičce'
    		)
    	);
    }

    Jistě jste si všimli, že jsme tímto příkazem zaregistovali hned dvě navigační menu. Hlavní menu a menu v patičce. Pokud byste chtěli jen jedno, odstraňte řádek „‚foot_menu‘ => ‚Menu v patičce’“, nebo naopak ukončete tento řádek čárkou a přidejte ješte jeden. Dbejte na to, že první parametr (tedy ‚foot_menu‘ a ‚primary_menu‘) musí být unikátní. Druhý slouží pro vaši orientaci, takže ideálně by měl být také unikátní, ale WordPress na tom netrvá.

    Tímto jste si zaregistrovali menu a nyní již naleznete v administraci navigačních menu (Vzhled->Menu) nalevo v boxu své dvě pozice („Hlavní menu“, „Menu v patičce“) a lze vytvářet menu a přiřazovat je těmto dvoum pozicím.

    Nyní tedy již zbývá pouze nechat zobrazit menu v šabloně. Je nutné zvolit místo, kde chcete menu zobrazit – to je na vás. Pokud modernizujete starou šablonu, budete nejspíš nahrazovat funkci „wp_list_categories“ umístěnou v souboru header.php nebo sidebar.php.

    Pro vložení menu do šablony použijte níže uvedený kód. Všechny uvedené parametry jsou parametry defaultní a proto, když je nebudete měnit, můžete je, pro zkrácení kódu, odstranit. Funkce wp_nav_menu má ještě další parametry (menu,walker,falback_cp), ale ty jsou pro začátečníka zbytečně komplikované a zřítka využitelné. Koho by zajímaly, nechť se obrází na kodex

     'primary_menu', //unikátní identifikátor menu nastavený v functions.php
      'container'       => 'div', //nebo 'nav' nebo false. Určuje, co se má použít jako element obklopující element UL samotného menu. False znamená, že žádný takový element nebude
      'container_class' => 'menu-{menu slug}-container', //třída (class) elementu UL obklopující samotné menu
      'container_id'    => '', //parametr ID elementu obklopujícího element UL samotného menu
      'menu_class'      => 'menu',  //třída (class) elementu UL obklopujcí menu
      'menu_id'         => 'nav', //parametr ID elementu UL obklopující menu
      'echo'            => true, //má se menu vypsat, nebo jen vrátit pomocí fce return?
      'before'          => '', //text před HTML tagem  'after' => '', //text za HTML tagem 'link_before'     => '', //text před samotným textem odkazu
      'link_after'      => '', //text za samotným textem odkazu
      'items_wrap'      => '
      %3$s
    ', //HTML markup vlastního menu
      'depth'           => 0, //do kolikáté úrovně zobrazovat podstránky. 0 znamená všechny úrovně
    );
    wp_nav_menu( $args ); ?>

    Exclude subcategory post from being viewed on parent category archive

    This default behavior, showing subcategory posts on parent category archive page may be undesirable. To exclude subcategory posts from parent category archive you have to modify the $query.

    As it is known that query_posts does not modifiy the main query, but executes new one, this is not the function we would use. It is preferable to use ‚pre_get_posts‘ hook to modify main query. And so I’m using this hook in my simple WordPress snippet for preventing of showing subcategory posts on parent category archive page. Here is the WordPress snippet – insert it into your functions.php

    function binda_limit_only_to_one_category( $query ) {
    	//check for main query and apply only on category archive page    
        if ( $query->is_category() && $query->is_main_query() ) {    	
    			//category__in does not bring posts from subcategories        
            $query->set( 'category__in', array( $query->get('cat') ) );
    			//unset cat which brings posts from subcategories
            $query->set( 'cat', '' );
        }
        //return query
        return $query;
    }
    add_action( 'pre_get_posts', 'binda_limit_only_to_one_category' );

    Exclude subcategory post from being viewed on parent category archive

    This default behavior, showing subcategory posts on parent category archive page may be undesirable. To exclude subcategory posts from parent category archive you have to modify the $query.

    As it is known that query_posts does not modifiy the main query, but executes new one, this is not the function we would use. It is preferable to use ‚pre_get_posts‘ hook to modify main query. And so I’m using this hook in my simple WordPress snippet for preventing of showing subcategory posts on parent category archive page. Here is the WordPress snippet – insert it into your functions.php

    function binda_limit_only_to_one_category( $query ) {
    	//check for main query and apply only on category archive page    
        if ( $query->is_category() && $query->is_main_query() ) {    	
    			//category__in does not bring posts from subcategories        
            $query->set( 'category__in', array( $query->get('cat') ) );
    			//unset cat which brings posts from subcategories
            $query->set( 'cat', '' );
        }
        //return query
        return $query;
    }
    add_action( 'pre_get_posts', 'binda_limit_only_to_one_category' );

    Chybějící odkazy ve WordPress 3.5

    Pokud si nainstalujete nový WordPress 3.5*, tak budete marně hledat v administrátorské postranní liště položku Odkazy (anglicky Links). WordPress tuto změnu dopředu avizoval a já jsem na to také účastníky školení WordPressu upozorňoval. Chybí-li Vám tato funkcionalita – doporučuji plugin Link Manager. * Používáte-li odkazy na svém webu a WordPress na novou verzi pouze upgradujete, […]