The Comment Goblin

While working at my new job, I’ve discovered a new creature, which I call the comment goblin. It goes through code and eats all of the comments, making the code extremely hard to read and follow as a lot of the code has been added over the years by multiple people, sometimes very poorly.

Ok, enough with the sarcasm, on with the point! Commenting your code is the second most useful thing you can do when writing software. The first most important thing is write your code so it doesn’t need comments. A lot of the code I’ve been working with follow neither of those guidelines, which surprises me as I work with several industry professionals who have been programming for years. I strongly believe that complex code or large projects should follow some strong commenting guidelines, giving usage examples, argument information, etc.

This is slightly less important when you write your code well, format it nicely, and expand things out so it’s readable. Code is read 10x more than it is written after all (If not more). It’s really frustrating for another programmer with no information on a project to pick it up and try to figure things out when you have functions like this:

static function fromDB($obj) {return $obj == '' ? array() : array_map('trim', explode(",", $obj));}

Does this make much sense to you? Would you know how to modify it? I’d give a commented version of the above function except I have no idea what it does, so instead here is an example of my code. Which is awesome.

    /**
     * Removes the walker paramater if no nav menu exists as it falls
     * back to wp_page_menu which our walker would break with
     *
     * @param array $args The array of arguments passed to wp_nav_menu
     * @return array
     */
    function wp_page_menu_args( $args ) {

        // Only remove the walker if it is ours
        if ( isset( $args['walker'] ) && get_class( $args['walker'] ) == 'Members_Only_Nav_Menu_Walker' ) {
            $args['walker'] = new Members_Only_Page_Walker();
        }

        return $args;
    }

This isn’t my best example, but you could always take a look at my PayPal IPN class or similar project. I do go on the heavy side of commenting, but only because I want novice programmers to be able to understand my more public code.

Easy WordPress Theme Options

For the most up-to-date information visit the plugin page

I’ve been getting really annoyed every time I want to add options to my theme and I have to copy a huge mess of code that just isn’t fun to use. You know what I mean. Most theme developers now include configurable options in their themes, which if you ask me, isn’t super easy.

So the other day I set out to write a class that theme developers could package with their file and have easy access to theme options. It’s as easy as adding my theme_options.php file to an include folder in your theme directory, and then adding this code to your functions.php (Using your option values obviously).

Download my ThemeOptions class

require_once( 'includes/theme_options.php' );

define( 'THEME_NAME' , 'Theme Template' );
define( 'THEME_SHORTNAME' , 'themetpl' );

ThemeOptions::add( 'sample_text_field', 'Its a text field'  , array( 'desc' => 'A description of the theme option', 'type' => 'text', 'default' => 'Default Value' ) );
ThemeOptions::add( 'sample_textarea'  , 'Its a text area'   , array( 'desc' => 'A description of the theme option', 'type' => 'textarea', 'default' => "Text\nTest" ) );
ThemeOptions::add( 'sample_checkbox'  , 'Its a checkbox'    , array( 'desc' => 'A description of the theme option', 'type' => 'checkbox', 'default' => 'enabled' ) );
ThemeOptions::add( 'sample_select'    , 'Its a select thing', array( 'desc' => 'A description of the theme option', 'type' => 'select', 'default' => 'Option 2', 'values' => array( 'Option 1', 'Option 2', 'Option 3' ) ) );
ThemeOptions::add( 'sample_radio1'    , 'Its a radio field' , array( 'desc' => 'A description of the theme option', 'type' => 'radio', 'default' => 'val1', 'values' => array( 'val1' => 'Text 1' , 'val2' => 'Text 2' ) ) );
ThemeOptions::add( 'sample_radio2'    , 'Its a radio field' , array( 'desc' => 'A description of the theme option', 'type' => 'radio', 'default' => 'val2', 'values' => array( 'val1' => 'Text 1' , 'val2' => 'Text 2' ) ) );

Now this may seem confusing at first, but if we expand it out, you’ll see it’s similar to other WordPress functions (I did the code like that for that specific reason):

$args = array(
    'desc' => 'This is a description of the option',
    'type' => 'text',
    'default' => 'This is the default value'
);

ThemeOptions::add( 'option_id', 'Option Name', $args );

And to get a value:

$val = ThemeOptions::get('simple_text_field');

Isn’t that easier that what you’ve been doing? I’ve encapsulated my code into a nice class to make everything super simple. The results should look similar to this (Located in Appearance > Theme Options):

Screenshot of the Theme Options Page

Download my ThemeOptions class

Members Only Menu Plugin

Visit my up-to-date page for this plugin

I released my my walker class as a super easy to use plugin (This doesn’t even require you to change your wp_nav_menu commands as it uses a filter to add it). I’ve submitted it to WordPress.org so I’ve linked to it below.

Just install and activate it, and then you can go to a page and mark it as Members Only.

Now featuring full support for wp_page_menu AND wp_nav_menu. Tested on WordPress 2.9+. Also fully compatible with PHP 4+!

Download my super awesome plugin now!

Must Have Have Plugins

With the amount of WordPress sites I’ve been doing lately, I’ve encountered a list of plugins I keep returning too. They may not be perfect, but they do what I need, and they do it well.

  • Contact Form 7
    • Really flexible contact form with changeable elements, optional CAPTCHA, multilingual support, recipients dependent on a drop down value, etc.
  • WPML
    • The best available multilingual plugin available for WordPress, adds a host of features for developing multi language sites.
  • TinyMCE Advanced
    • Adds more commands to the WordPress default editor, such as tables and the option to stop removing extra breaks.
  • Members
    • Adds enhanced role and capability management features, a must for any large or complex CMS built on WordPress. It’s very powerful
  • HTML and Flash Video Player
    • A nice plugin adding shortcodes for inserting a Flash/HTML5 video player in WordPress posts
    • Requires a hook in the template you are using
    • Shortcode is [videoplayer file=”video/video.flv” /]
  • WP e-Commerce
    • Full e-commerce functionality wrapped up in a nice plugin. Support for popular payment gateways like PayPal and Google Checkout. Very bloated though.
  • Fluency Admin
    • Changed up the WordPress admin area adding a much needed visual makeover, and some minor new features.
  • Really Simple CAPTCHA
    • Required to add CAPTCHA functionality to Contact Form 7, can be used in your own plugins as well. Very simple, not all that secure but easy to

WordPress Walker Classes

Walkers are used in WordPress to recursively handle data such as menus. As defined in the WordPress codex

The walker class encapsulates the basic functionality necessary to output HTML representing WordPress objects with a tree structure. For instance pages and categories are the two types of objects that the WordPress 2.2 code uses the walker class to enumerate. While one could always display categories as you wished by using right func and looping through them using it takes a great deal of work to arrange subcategories below their parents with proper formatting. The walker class takes care of most of this work for you.

Now, unfortunately there is very little good documentation about Walker classes, even though they give you more customization and flexibility then the default code, all without modifying core WordPress files which is perhaps the most important part. I set out this last week to allow my client to create a members only page which he could add to the site navigation, and have it only show up if the user was logged in. This turned out to be more difficult than I initially expected as private pages cannot be added to the menu.

After searching the Internet and finding nothing, I did the next best thing: Searched through the WordPress code. I eventually came up with this, which adds a checkbox saying “Is Members Only?” to the page editor. Then I added some code to my theme’s functions.php, which could easily be put in a plugin instead which checks to make sure the user is logged in. Now to make it selectively appear in the menus, I wrote my only walker class, extending the default one.

Here is my code:

add_action( 'wp' , 'check_for_members_only' );

function check_for_members_only() {
	global $post;

	if ( get_post_meta( $post->ID , '_members_only' , true ) && !is_user_logged_in() ) {
		header( 'Location: /wp-login.php' );
		exit();
	}
}

The above snippet is fairly simple. It executes right after the post data is set, and checks if some post meta is set. If it is, we redirect to the login page.

function add_members_only_meta_box() {
    add_meta_box( 'add_members_only_meta' , 'Members Only' , 'add_members_only_meta' , 'page' , 'side' , 'high' );
}
add_action( 'add_meta_boxes' , 'add_members_only_meta_box' );

function add_members_only_meta() {
    global $post;

    $meta_box_value = get_post_meta( $post->ID , '_members_only' , true ); 

    if ( $meta_box_value == 'true' ) {
        $meta_box_value = 'checked="checked"';
    }

    echo '<input type="hidden" name="members_only_nonce" id="members_only_nonce" value="' . wp_create_nonce( 'members_only' ) . '" />';
    echo '<input type="checkbox" name="members_only" id="members_only" value="true" '.$meta_box_value .' /> Restrict To Members?';
}

/* When the post is saved, saves our custom data */
function members_only_save_postdata( $post_id )
{
    // verify this came from the our screen and with proper authorization,
    // because save_post can be triggered at other times
    if ( !wp_verify_nonce( $_POST['members_only_nonce'], 'members_only' ) )
    {
        return $post_id;
    }

    // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want
    // to do anything
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return $post_id;

    // Save
    update_post_meta( $post_id , '_members_only' , $_POST['members_only'] );

    return $post_id;
}
add_action( 'save_post' , 'members_only_save_postdata' );

This code is also fairly straight forward. We add a meta box to the page editor (Look at the add_meta_box, I specify page). We also add some code to save our post meta, prefixing it with an underscore so it is hidden from the meta box interview.

Now here is the walker class.

class Walker_Nav_Menu_CMS extends Walker_Nav_Menu {
	function start_el(&$output, $item, $depth, $args) {
		global $wp_query;

		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

		$class_names = $value = '';

		$classes = empty( $item->classes ) ? array() : (array) $item->classes;

		$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
		$class_names = ' class="' . esc_attr( $class_names ) . '"';

		if ( !get_post_meta( $item->object_id , '_members_only' , true ) || is_user_logged_in() ) {
			$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
		}

		$attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
		$attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
		$attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
		$attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

		$item_output = $args->before;
		$item_output .= '<a'. $attributes .'>';
		$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
		$item_output .= '</a>';
		$item_output .= $args->after;

		if ( !get_post_meta( $item->object_id, '_members_only' , true ) || is_user_logged_in() ) {
			$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
		}
	}

	function end_el(&$output, $item, $depth) {
		if ( !get_post_meta( $item->object_id, '_members_only' , true ) || is_user_logged_in() ) {
			$output .= "</li>\n";
		}
	}
}

This is almost exactly the same as the default nav function, except I added the line “if ( !get_post_meta( $item->object_id, ‘_members_only’ , true ) || is_user_logged_in() ) {“. Now, in this case I wanted to modify only the Nav Walker, without editing core files. I didn’t need to change much, so all I did was extend the default Nav Walker, instead of the base Walker class.

If you look through the code, it’s not really hard to understand. The walker class has several functions, start_el, end_el, walk, start_lvl, and end_lvl. You can extend the base classes and implement your own versions of these functions if you want. I’ll explain what these do.

start_lvl – Creates the <ul>
end_lvl – Creates the </ul>
start_el – Creates the <li right to the </li> but excluding the </li>
end_el – Creates the </li>
walk – This is a fairly complex function that calls the above functions depending on if a submenu needs to be created, or closed, etc.

I would recommend looking at the Walker class in wp-includes/classes.php and the other classes that extend the Walker class from wp-includes/nav-menu-templates.php.

Now the most important part is getting your code to use the new walker class. This is super simple:

wp_nav_menu( array( 'walker' => new Walker_Nav_Menu_CMS() ) );