When polyfills just don’t feel right: automatically build your IE-fix CSS with SASS. http://t.co/cbnrMg5UDZ and http://t.co/KLpM1eNKtC #ie8 #css #sass
Webdeveloper
Build a fully customized WordPress login: Those annoying redirects
I’ve built quite a few custom login-forms in WordPress. There are, as always, a lot of ways to realize that, but nearly all the clients I worked with, had similar requirements: On the one hand they wanted to preserve the usual WordPress login-form to let administrators, editors and authors sign in to wp-admin. On the other hand they wanted another usergroup to sign in to their site via a fully customized WordPress login-screen, to download protected documents or whatever.
Customized WordPress login-form
Generally the problem is solved fairly easily, using the WordPress-API. You can print out a standard login-form by using wp_login_form wherever in your theme you want it. There is even a way to specify the page, the user should be redirected to after a successful login. Here is an example, redirecting you to the home page:
<?php
wp_login_form( array(
'redirect' => get_bloginfo('url'),
'form_id' => 'sign-in',
'label_log_in' => __( 'Sign in' ),
) );
?>
If you need to adjust the HTML-output, you can build your own sign in form markup by saving a file named searchform.php in your theme folder. Then you are just a few stylesheet-rules away from your customized form, with working login.
Handling login-fails
The problems begin when you fail to log in, because writing in a wrong username and/or password doesn’t redirect you to your customized form, it redirects you to the wp-admin site. Since the signing-in user is not supposed to log in to wp-admin, this redirect doesn’t make any sense. But again we find a straightforward solution in the WordPress-API. Add these lines to your functions.php:
function custom_login_failed( $username ) {
$referrer = $_SERVER['HTTP_REFERER'];
if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
// redirect to your login page, you might want to add a parameter login_failed
// to show an error message or something like that
wp_redirect( ... );
exit;
}
}
add_action( 'wp_login_failed', 'custom_login_failed' );
You might think that’s all, but not so fast …
Handling empty logins
There is yet another way to get redirected to the wp-admin login form, and that is when you just don’t enter anything. Submit the form with an empty username and password field and you are on wp-admin again. That is because the wp_authenticate function, which handles redirection, ignores empty_username and empty_password as error codes and that is why our wp_login_failed action never fires. The solution is to change these error codes, if the user logs in from another site than wp-admin or wp-login.php. This is done by the following filter function (note the filter priority, which is important here).
function custom_authenticate( $user, $username, $password ) {
if ( is_wp_error( $user ) && isset( $_SERVER[ 'HTTP_REFERER' ] ) && !strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-admin' ) && !strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-login.php' ) ) {
$referrer = $_SERVER[ 'HTTP_REFERER' ];
foreach ( $user->errors as $key => $error ) {
if ( in_array( $key, array( 'empty_password', 'empty_username') ) ) {
unset( $user->errors[ $key ] );
$user->errors[ 'custom_'.$key ] = $error;
}
}
}
return $user;
}
add_filter('authenticate','custom_authenticate', 31, 3);
Other ways?
I know of one alternative to the above code: Since wp_authenticate is a pluggable function, you could simply overwrite it. But you can only do this with a plugin, so you have to add a plugin to your site and activate it, which I think is a bit more hassle.
Is there another way you know of? Please let me know in the comments.
Problems we don't have?
Inspiring read on how much we should struggle to support outdated browsers. Favorite quote: “Problem 3: IE6 and 7 … what are you doing?”
New blog layout
My blog just got back from a trip in a flying DeLorean, and finally landed in 2013 – @pixelcrook, you are my hero. http://www.danielauener.com
WordPress pagination: Simple and reusable without a plugin
Pagination might be one of the most common UI patterns on the web. The concept of showing just a limited number of articles, posts or whatever and making the reader click through the rest, comes in quite a few variations. Google’s search results come to mind or more advanced infinite scroll solutions. Naturally, WordPress implements this concept and I have to admit that, for some time, I found it quite difficult to use, especially with custom queries.
As is so often the case, the difficulties weren’t caused by the API-implementation or documentation, but by my not reading it. So, after realizing that, there was nothing left to do but work it out and here is the solution I use in my starter-theme. It contains a file named pagination.php, with the following content.
<?php
global $paginated_query;
global $wp_query;
if ( !$paginated_query ):
$paginated_query = $wp_query;
endif;
if ( $paginated_query->max_num_pages > 1 ) : ?>
<div class="pagination">
if ( !$current_page = get_query_var('paged') ) :
$current_page = 1;
endif;
echo paginate_links(array(
'base' => get_pagenum_link(1) . '%_%',
'current' => $current_page,
'total' => $total
)); ?>
</div><?php
endif;
?>
The great thing is that the paginate_links function does all the page-logic for you, if you just provide it with a current page number and the total number of pages. So if you want to paginate your main loop, all you have to do is to include this file. Since we don’t define a $paginated_query, the parameters will be taken from the global $wp_query.
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
...
<?php endwhile; endif; ?>
<?php get_template_part("pagination); ?>
But it’s quite easy, even with a custom query. Here you have to define the $paginated_query variable, before including pagination.php and giving the paged param to the WP_Query-object, so the requested page can be queried.
<?php
$custom_query = new WP_Query( array(
'post_type' => 'page',
'posts_per_page' => 3,
'paged' => ( !$current_page = get_query_var('paged') ) ? 1 : $current_page
) );
?>
<?php if ( $custom_query->have_posts() ) : while ( $custom_query->have_posts() ) : $custom_query->the_post(); ?>
...
<?php endwhile; endif; ?>
<?php
$paginated_query = $custom_query;
get_template_part("pagination);
?>
That’s how I do it, but I’m always interested in other solutions.
Please comment if you have a better or alternative solution!
