Get email alerts about 404 errors on your WordPress site

Ever wanted to get email alerts about 404 errors on your WordPress site?

Jeff Starr over at WP Mix posted a snippet yesterday for doing just that. And I, having a little time on my hands, decided to give it the ol’ OOP-once-over.

The original WP Mix post called for dropping the entire snippet into the top of your WordPress theme’s 404.php file, but I generally don’t like to clutter up my template files with extra non-theme stuff. So I converted it into a class which can then be easily instantiated in with these two lines:

if ( class_exists( 'Clean_404_Email' ) )
	new Clean_404_Email;

Not bad, considering the original snippet called for dropping in 83 lines of extra code!

I also converted the email format to a use a table, just so it’s a little more orderly about it.

Many users take advantage of freely-available tools like Google’s Webmaster Tools or other services to track a site’s 404 errors. This class gives you the short and sweet of it, and there’s no waiting around. If somebody gets a 404 on your site, WordPress will email you on the spot.

The gist is available on GitHub and also embedded below.

Photo used under CC. Photo by Jeremy Keith (adactio/Flickr)

Force sub-categories to use the parent category template

A couple of times in the last several years, I’ve needed sub-categories to inherit their parent’s archive template, but it’s just not something the Template Hierarchy supports. I’ve seen several plugins that tried and failed to do it, so finally I wrote a little filter that in my testing, works any number of levels deep, from sub-sub-categories to sub-sub-sub-categories. Enjoy!

function new_subcategory_hierarchy() {	
	$category = get_queried_object();

	$parent_id = $category->category_parent;

	$templates = array();
	if ( $parent_id == 0 ) {
		// Use default values from get_category_template()
		$templates[] = "category-{$category->slug}.php";
		$templates[] = "category-{$category->term_id}.php";
		$templates[] = 'category.php';		
	} else {
		// Create replacement $templates array
		$parent = get_category( $parent_id );

		// Current first
		$templates[] = "category-{$category->slug}.php";
		$templates[] = "category-{$category->term_id}.php";

		// Parent second
		$templates[] = "category-{$parent->slug}.php";
		$templates[] = "category-{$parent->term_id}.php";
		$templates[] = 'category.php';	
	return locate_template( $templates );

add_filter( 'category_template', 'new_subcategory_hierarchy' );

Add ‘Edit User’ Toolbar link on author archives

Currently it takes 3-4 steps to get to a user’s edit screen from the front-end, which really comes down to a lot of wasted time when you’re working on a user-heavy site. One of my biggest usability pet peeves is unnecessary extra steps. On the WordPress front-end, we have ‘Edit *’ Toolbar links for objects like taxonomy terms and post types, so why not users?

The question was raised recently by John Blackbourn on Trac and I think it has a lot of merit. I’ll concede that the inherent behavior of an edit link on an archive shouldn’t be to edit an object but an author archive (usually) serves dual purposes: Author info and author archive.

Here’s the snippet I worked up from @lessbloat’s revised patch:

function ww_toolbar_edit_user_link( $wp_admin_bar ) {
	$current = get_queried_object();
	// Check that it's a WP_User object and user is editable
	if ( is_a( $current, 'WP_User' ) 
		&& current_user_can( 'edit_user', $current->ID ) ) {
		// Add the menu
		$wp_admin_bar->add_menu( array(
			'id' => 'edit',
			'title' => __( 'Edit User' ),
			'href' => get_edit_user_link( $current->ID ),
			'meta' => array(
				'title' => __( 'Edit User' )
		) );
add_action( 'admin_bar_menu', 'ww_toolbar_edit_user_link', 81 );

Query based on whether posts have a featured image

Ever need to query for posts based whether they have a post thumbnail? This can be accomplished by adding 'meta_key' => '_thumbnail_id' to the query args:

$args = array(
	'posts_per_page' => 1,
	'meta_key' => '_thumbnail_id'
$my_query = new WP_Query( $args );

if ( $my_query->have_posts() ) : while ( $my_query->have_posts() ) : $my_query->the_post();

Easy way to check if jQuery is already enqueued

Had a plugin wreaking some havoc today because it was overloading jquery.js with a minified, older version. Plugin authors: There’s a really simple way to check if jQuery or a jQuery library is already registered and enqueued. This covers really obscure edge cases where a plugin may have de-registered WordPress’s default scripts.

The offending code:

wp_register_script('myjquery', '', true, '1.6.4', false);

The fix:

// If jQuery isn't already enqueued, register and enqueue it
if ( ! jQuery ) {
	wp_register_script('myjquery', '', true, '1.7.2', false);

HowTo: Disable Access to the WordPress Dashboard for Non-Admins

Update: I had a few requested to bundle this into a plugin so I did. You can download it here.

Currently, I’m working on a site where we didn’t want non-admins to even be able to access the wp-admin dashboard. I searched around quite a bit looking for a complete shutoff-solution but most of the results detail how to literally disable the “Dashboard” menu in wp-admin.

Finally, trolling the comments on a like-solution in a post by c. bavota, I stumbled across a simplified version of bavotasan’s function that does exactly what I want, plus it redirects unworthy users to the homepage!

The simplified function was authored by somebody going only by the moniker of Jake.

It’s a pretty simple solution. It adds an action calling a function called ‘redirect_dashboard’ which checks the user level, and if the currently-logged-in-user is unworthy, they get bounced to the homepage. Pretty neat. On line #4, the function checks the user level, with the default set as ‘level_10’ or administrator. I modified this to ‘level_7’ to exclude anyone below the Editor level, but you could choose whichever capability level suits your purpose. Vist the Roles and Capabilities Codex page to find out more about user levels.

Here’s the snippet (which should be added to your theme’s functions.php file)

add_action('admin_init', 'no_mo_dashboard');
function no_mo_dashboard() {
  if (!current_user_can('manage_options') && $_SERVER['DOING_AJAX'] != '/wp-admin/admin-ajax.php') {
  wp_redirect(home_url()); exit;