When polyfills just don’t feel right: autobuild your ie-fix css with SASS. http://t.co/cbnrMg5UDZ and http://t.co/KLpM1eNKtC #ie8 #css #sass
Build a fully customized WordPress login: Those annoying redirects
I’ve build 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 into wp-admin. On the other hand they wanted another usergroup to sign in into 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 easy, 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 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. Than 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 login, 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 login to wp-admin, this redirect doesn’t make any sense. But again we find a straight forward 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 plugable function, you could simply overwrite it. But this you only can do 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, landed in 2013 finally – @pixelcrook you are my hero. http://www.danielauener.com
WordPress pagination: Simple and reuseable without a plugin
Pagination might be one of the most seen ui-patterns on the web. The concept of showing just a limited amount of articles, posts or whatever and making the reader click through the rest, comes in quite a few variations. Googles search results are coming 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 so often, the difficulties weren’t caused by the API-implementation or documentation, but myself not reading it. So, after realizing that, there was nothing left than working 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 numbers 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!