Temporary look change

Yes. Until the end of the year this site will be rocking the 2016 default theme that is under construction. Yes, you read it right. It looks vastly different from the last theme. I may switch it out after the new year but until then, this will be the look.

Next steps

Down the line I will be making a few changes of course to sort of suit the needs but for the most part it will be for testing purposes. I want this site to be a guinea pig a little bit if you hadn’t noticed.

In the coming days, I’ll be creating a child theme so I can expand upon the theme and perhaps break it along the way.

This will be fun!

What makes a good WordPress theme

I’ve been reviewing themes for quite some time and over the course I’ve learned a lot about the good parts, the bad parts, and the in betweens. All these themes have a few things in common. What I like to call guiding principles. I think of them much like I do the principles of design; simple rules to making a WordPress theme.

We all have our take and this is mine:

  • Error free
  • Follows core implementation and best practices
  • All around user-friendly

Just three things. Sounds a little crazy but it is true. I’ll explain each one a little more.

Error Free

Yes, error free. This includes CSS, JavaScript, HTML, and PHP. Now, that sounds simple right? It can be. What I mean is not just those. I also mean WordPress related errors. Believe it or not, there are times when WordPress does throw out some errors.

If you know, or follow, WordPress development, you know there are a few things to look for. Four functions and one setting can do a lot of damage. The _deprecated_* functions, _doing_it_wrong, and define( 'WP_DEBUG', true ) can create a very bad experience for not just users but end-users as well. Clearly we would like to avoid all of these things when possible. There are times when some things are not possible but you can prepare for some.

Yes, there are times when CSS/HTML may create an error but it could be caused by a user inputting arbitrary HTML/CSS in some form or another so that takes less precedence. The ones to be super mindful of are JavaScript, PHP and the WordPress related ones because as a theme author you can control this. You can do this by using an alpha version, beta version and release candidates. There is a plugin that allows you to do this: WordPress beta tester. It is a great and powerful plugin for themes and plugins to take advantage of. You know the best part about it? It’s FREE!

Best Practices

Yes I said it. The thing to remember here is that those can change. Much like core does and has. To elaborate, a theme should be able to be switched without the user even having to worry about losing any content. A theme makes the design decisions. No, I don’t mean a user can’t change colors or even a layout but it does mean that it should have only the needed options. Minimalist if you will.

A good example of this would be the Twenty Fifteen theme. Yes, I am linking to it because it has a great color scheme selector. Notice that it doesn’t have options for specific things the theme has. There are some that use the customizer for link colors, header title changes and simple things that a CSS plugin can do or even a child theme. Yes, a child theme. Any theme can have a child theme. If it makes it hard to create one, odds are you may have to rethink a few things.

As I mentioned there should be no reason for a user to lose any content. What this means is as a theme author, you have to think about what is being saved to the database. What things can be migrated when a user wants to change from Theme A to Theme B or Theme D.

Yes, that can feel limiting but let me give you an example of this. You buy an iPod – yes, they still exist – but you had a Sony mini-disc player – yes, they too, still exists – and you want to transfer all your music to the new iPod. Well, the Sony player used a different format for saving those songs you loved so much. Yes, Nicki Minaj, Alice Cooper, Aerosmith, Beethoven, and that Blues Clues theme you wanted to transfer over won’t play because they are in a different format. You’ve created more work for not only the user but a terrible experience as well. You’re going to tell your friends the iPod doesn’t support this and can’t do this and that and all because the mini-disc player ( your theme ) didn’t follow a standard of MP3.

Yes, it does seem a little off to mention that but think about what the next theme author will have to explain. You may be the next theme author that explains why their slider isn’t showing up in the right place.

Friendly

And I mean FRIENDLY! Okay, now that the sugar has somewhat worn off, let me explain a little more. A theme is child friendly and plugin friendly. What do I mean by child friendly? Simple.

WordPress has a great way of making themes and making those changes without a user having to lose a lot of those changes. A great way of course is through a plugin. Another is a child theme. What’s amazing is that a child theme overrides the parent theme when it comes to template files. If you don’t understand those terms, please read the provided links. It will make sense once you do. I’ll be waiting.

Okay, now, I also mentioned plugin friendly. What does that mean? There are tons of plugins, and I mean tons of plugins. The way some plugins integrate with themes can be a hassle and there are several ways of doing that too. Some use a template tag, some use an action hook, a filter hook, and some use classes. What’s the best? The downside is I don’t have the exact answer but I can show you a quick way of making it easy for not only plugins but themes to take advantage of it. Using do_action and apply_filters.

Yes, WordPress has a great way of making sure that your theme does not create fatal errors. Using those two will not only make using child themes a lot friendlier for your users but plugins as well. Worse case scenario is that a plugin doesn’t use the right name for the hook or filter and it doesn’t work. Simple fix. Let’s make a quick example:

// somewhere in the header.php file
$col_count = absint( apply_filters( 'jc_column_count', 4 ) );
?>

<div class="col-<?php esc_attr( $col_count ); ?>">

What is super amazing is that a child theme or plugin can filter that. This was also mentioned a long time ago by Andrew Nacin. It is a great read and it does amaze me how many still haven’t adopted this.

The last bit I would like to go over is what may be a super important part for the user of a theme. The documentation. Yes, documentation. Even something so simple as how to set up a social menu can be tricky for a new person. When I say user I do mean both the developer and the site’s user. They may not always be the same person. Remember, you are thinking externally here.

Two or three column section

A while back I wrote a quick and dirty tutorial on how to display more than one page. This can be done in a number of different ways. You can read about them in other tutorials and guides because this time I’ll go over another method using the WP_Query method. The codex page some really great ways and examples of using it to your advantage, I highly recommend you give it a skim and return to this.

So, on to the code!

What I’ll be using is a switch statement, an active callback, and of course the customizer API.

First we will create the settings and controls:

$wp_customize->add_section( 'demo-front-sections',
				 array(
					 'title' => __( 'Front page sections', 'text-domain' ),
					 'description' => __( 'Choose what pages to show on the front page panels', 'text-domain' ),
					 'priority' => 1,
					 'active_callback' => 'is_front_page'
				 ) );
$wp_customize->add_setting( 'col-count',
				 array(
					'default' => 2,
					'sanitize_callback' => 'absint'
				 ) );
$wp_customize->add_control( 'panel-count',
				 array(
					'settings' => 'col-count',
					'label' => __( 'How many panels on this section', 'text-domain' ),
					'type' => 'radio',
					'choices' => array( '2' => 2, '3' => 3 ),
					'section' => 'demo-front-sections',

				 ) );

// Register the page settings to get the IDs
$wp_customize->add_setting( 'page-1',
				 array(
					'default' => 0,
					'sanitize_callback' => 'absint'
				 ) );
$wp_customize->add_setting( 'page-2',
				 array(
					'default' => 0,
					'sanitize_callback' => 'absint'
				 ) );
$wp_customize->add_setting( 'page-3',
				 array(
					'default' => 0,
					'sanitize_callback' => 'absint'
				 ) );

// Set the controls
$wp_customize->add_control( 'panel-1',
				 array(
					 'settings' => 'page-1',
					 'label' => __( 'Pick what page you would like to showcase', 'text-domain' ),
					 'type' => 'dropdown-pages',
					 'section' => 'demo-front-sections'
				 ) );
$wp_customize->add_control( 'panel-2',
				 array(
					 'settings' => 'page-2',
					 'label' => __( 'Pick what page you would like to showcase', 'text-domain' ),
					 'type' => 'dropdown-pages',
					 'section' => 'demo-front-sections'
				 ) );
$wp_customize->add_control( 'panel-3',
				 array(
					 'settings' => 'page-3',
					 'label' => __( 'Pick what page you would like to showcase', 'text-domain' ),
					 'type' => 'dropdown-pages',
					 'section' => 'demo-front-sections',
					 'active_callback' => 'panel_countcheck'
				 ) );

You’ll notice I used a basic active callback for the section so that the section will only show up on the front page. You may also notice that I’ve added a callback to the third control. We haven’t created that callback so let’s do it:

function panel_countcheck( $value ){
	if ( get_theme_mod( 'col-count' ) > 2 ){
		return true;
	}
	return false;
}

Great! Now what does it do? Let’s break it down a little. So, if the first value ( col-count ) is greater than 2, then let’s show this control, otherwise we won’t. Pretty self-explanatory, right?

Great now we just need to display this on a page template, or the front page ( in our case ). We use get_theme_mod to get the values and the code will look a little like:

// get setting for how many
$count = intval( get_theme_mod( 'col-count', 2 ) );
// create an array for the new query
$ids= array();
// get the pages
$ids[] = intval( get_theme_mod( 'page-1', 0 ) );
$ids[] = intval( get_theme_mod( 'page-2', 0 ) );
if ( $count > 2 ){
	$ids[] = intval( get_theme_mod( 'page-3', 0 ) );
}

$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => $ids, 'orderby' => 'post__in' ) );

switch( $count ){
	case 2:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-2">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
	case 3:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-3">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
}

Yeah, it is a little messy but we will break it down and explain what does what.

The first setting we get is the column count. You’ll see that I am using intval because we want to make sure that we are setting an integer. The value being passed from the customizer setting is an ID number that corresponds to a page ID, so we make sure that it really is an integer.

$count = intval( get_theme_mod( 'col-count', 2 ) );

Next up, we get our pages and build up the array that we will pass our new WP_Query. As you can see, we first get the first two pages and conditionally add the third if the $count is greater than 2. Remember this is the setting that the user picks.

$ids[] = intval( get_theme_mod( 'page-1', 0 ) );
$ids[] = intval( get_theme_mod( 'page-2', 0 ) );
if ( $count > 2 ){
	$ids[] = intval( get_theme_mod( 'page-3', 0 ) );
}

From there, we build up the new query. Pretty simple. We make sure that the post type is a page, and the order is maintained by what we pass it.

$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => $ids, 'orderby' => 'post__in' ) );

Now we get to the switch statement! This is where the fun sort of begins.

switch( $count ){
	case 2:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-2">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
	case 3:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-3">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
}

Okay. Let’s look over the lines a bit. As you can see we pass it the $count variable we first created, which houses the option of whether to show 2 pages or 3. We create a case for each one and as you can see the only real difference here is the class. For showing two pages it is 2-col and for the 3 it is 3-col. You can create a quick wrapper for that if you want so it can be extended by a child theme like:

function jc_classes(){
	$classes = array();
	$classes[] = 'span';
	$cols = get_theme_mod( 'col-count', 2 );
	switch( $cols ){
		case 2:
		$classes[] = 'col-2';
		break;
		case 3:
		$classes[] = 'col-2';
		break;
	}
	
	return 'class="' . esc_attr( implode( ' ', apply_filters( 'jc_custom_classes', $classes ) ) ) . '"';
}

From there we can lose the switch statement and use:

$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => $ids, 'orderby' => 'post__in' ) );
while( $query->have_posts() ): $query->the_post();
	echo '<div ' . jc_classes() .'>';
		the_title( '<h2>', '</h2>'); the_content();
	echo '</div>';
endwhile;
wp_reset_postdata();

What’s really nice is you can use basic CSS to style it. A quick snippet:

.col-2 {
	float: left;
	width: 50%;
}

.col-3 {
	float: left;
	width: 33%;
}

So, go on, experiment, and fiddle around with the code a bit. Do remember I used basic things, so be sure to add the proper settings, text, and values for your needs.

Customizer: dropdown category selection

This is just a quick code snippet that may help at least one person. I know it will. Earlier today I was looking over a theme and it was driving me crazy to see them re-inventing the wheel. A simple dropdown that core uses in order to display the categories. The way core uses choices is an associative array. The array key is the $value and the array value is used for the label. What does this mean?

It means that often times you have to flip things around because core can get certain values in a different manner. A great example is the get_page_templates function. The following is one way of creating this array.

// we get all the available templates
$templates = array_flip( get_page_templates() );

// new array is
$templates = 
	array (
	'templates/home.php' => 'home',
	'templates/featured.php' => 'featured posts',
	'templates/widgetized.php' => 'Widgetized Page'
	)

Do keep in mind that is just for that particular function. There are several other functions that return either arrays or objects, so it is in your best interest to learn how and what each function returns data. I say this because the above code uses a basic PHP function in order to re-create the array. The function itself returns things the other way around. The codex page does a good job of explaining it.

In this post we will go over the get_categories function. It returns an array but not the way we want in order to use in the customizer. In order to do so we have to get a little creative in building the array.

// create an empty array
$cats = array();

// we loop over the categories and set the names and
// labels we need
foreach ( get_categories() as $categories => $category ){
	$cats[$category->term_id] = $category->name;
}

// we register our new setting
$wp_customize->add_setting( 'cats_elect', array(
	'default' => 1,
	'sanitize_callback' => 'absint'
) );

// we create our control for the setting
$wp_customize->add_control( 'cat_contlr', array(
	'settings' => 'cats_elect',
	'type' => 'select',
	'choices' => $cats,
	'section' => 'my_section',  // depending on where you want it to be
) );

This will return an integer for the category. Hence the absint sanitation callback. From there all we would have to do to get our setting is use:

$cat_id = intval( get_theme_mod( 'cats_elect', 1 ) );

You’ll notice I’ve used intval around the get_theme_mod function, that is so we make sure that we are getting an integer from our saved setting just in case. You can never be too careful, right?

So, there you have it! Just a few lines of code and we have a dropdown of our categories.

Working with the WordPress Customizer

Recently the Theme Review Team chose to make the customizer as the format of creating theme options. I love it! Yes, I was in favor of it. I have my reasons. I know there are some people that still don’t fully grasp the customizer and most likely won’t. All good! Some take a little more time than others; I know I do sometimes with certain things.

How it works

Okay. This little post will deal with customizer settings, controls, sections and panels. Yes. At the time of this writing the WordPress version is 4.2.1 with 4.3 just beginning. In the following I will make an attempt at giving you ( the reader ) a little more insight into how the WordPress customizer works and what is available within the customizer.

In order to understand the customizer a little more I dove into the core code. I asked myself a simple question, “when and where is it being created?”

Funnily enough it is done in one simple function. _wp_customize_include. It is a callback function that is hooked to plugins_loaded. Yes, I went ahead and looked up a lot of the code for you. What’s pretty cool is that in order for the customizer to work it needs five files. Yes, five. To a degree 7 but the other two are the customize.php and class-wp-customize-widgets.php files. For the purpose of this post I’ll only really dive into the five customizer ones.

Let’s look at the function:

function _wp_customize_include() {
	if ( ! ( ( isset( $_REQUEST['wp_customize'] ) && 'on' == $_REQUEST['wp_customize'] )
		|| ( is_admin() && 'customize.php' == basename( $_SERVER['PHP_SELF'] ) )
	) )
		return;

	require( ABSPATH . WPINC . '/class-wp-customize-manager.php' );
	// Init Customize class
	$GLOBALS['wp_customize'] = new WP_Customize_Manager;
}

The key thing to remember is when you are creating your options, you are passing an object. The $wp_customize global object to be a little more specific. As you can tell from the function above, you are creating an instance of the WP_Customize_Manager and setting that as the $wp_customize global variable that can be accessed by using:

global $wp_customize;

Looking at the __construct method, it loads the needed files and adds a few filters and hooks in order for the magic to happen. Totally awesomesauce!

Boom! We have our customizer! Great! But how do we add stuff?

Adding things

In order to add our theme options we have to hook to the right place. The codex has a great explanation on this, though currently it is missing a section on how to add panels. Yes, you can add panels in order to make your theme option logic make some sense for a user.

So, in order to add things we need to know how, right? Right! What’s pretty neat is that the customizer does this with built in methods. Yes, it is very object oriented. One of the other reasons I like it. There are four methods that will help in creating a great customizer experience.

$wp_customize->add_setting();
$wp_customize->add_control();
$wp_customize->add_section();
$wp_customize->add_panel();

I say customizer experience because as a developer you will have to think about the logic of your theme options. That’s great and all but what actually starts it all? The part that we hook to in order to start our theme options is the customize_register hook. This is done from within your theme by using:

add_action( 'customize_register', 'my_theme_customize_regiter' );
function my_theme_customize_register( $wp_customize ){
	// Theme settings/options code goes here
}
// or if using a class
add_action( 'customize_register', array( 'My_Class_customize_register', 'register' ) );
class My_Class_customize_register {
	public function register(){
		// Theme settings/options code goes here
	}
}

Got it? Cool! Let’s keep moving! Let’s break down each method a little more.

The methods

What’s super cool is that the customizer makes it super easy to create a theme option experience. It does this with four different methods. Let’s take a look at each one and what each one has to offer.

add_setting

The first one we will look at is the settings. In order to create a theme option in the customizer we use the $wp_customize->add_setting method. It takes two arguments. The first one is the ID of the setting and the second is an associative array. It looks a little like:

$wp_customize->add_setting( 'theme_option', array(
	'default' => '', // The default setting
	'type' => '', // can use 'theme_mod' or 'option'
	'capability' => '', // generally 'edit_theme_options'
	'transport' => '', // can use 'refresh' or 'postMessage'
	'theme_supports' => '', // internally used in customizer
	'sanitize_callback', // the callback before setting is saved to database
	'sanitize_js_callback' => '' // used for the JS value
	) );

You don’t have to use all of them. The ones that matter most are the default, option, transport, and sanitize_callback arguments. The reason option is one that matters is in the way it will save the options into the database. The sanitize_callback matters because it runs before the setting is saved to the database so you have to make sure to sanitize it. The transport value can be important if you want the page to do a full refresh or if it will be AJAXified.

add_control

The next one to look at is the $wp_customize->add_control. This is what the user will see. Much like the add_setting it, too, we have to pass two arguments. The first one being a unique ID, and the second being an associative array.

$wp_customize->add_control( 'option_control', array(
	'label => '', // label for the control
	'description' => '', // description of the control
	'settings' => '' // the setting 
	'section' => '', // core ones are: 'title_tagline', 'colors', 'header_image', 'background_image', 'nav', 'static_front_page'
	'type' => '', // core ones include: 'checkbox', 'radio', 'select', 'textarea', 'dropdown-pages', 'text'
	'choices' => array(), // associative array of 'value' => 'option user sees'
	'priority' => '', // the higher the number the lower it will appear from the top
	'input_attrs' => array(), // associative array of 'attr' => 'value'
	'active_callback' ='' // based on preview context
	) );

So, we have a few options with the controls. Cool, right? What’s even cooler is that there are few others to use. You can also use WP_Customize_Image_Control, WP_Customize_Upload_Control, WP_Customize_Color_Control, and WP_Customize_Media_Control. They just require a little extra code.

$wp_customize->add_control( new WP_Customize_Media_Control( $wp_customize, 'media_control', array(
	'label' => 'Image selection',
	'description' => 'Choose an image',
	'settings' => 'default_value',
	'section' => 'random_slider'
) ) );

add_section

Great! Now that we know how to create a setting and a control, we can look at how to create a section to hold those settings. You’ll notice I’m using settings and options a little interchangeably. As stated earlier you can choose how to save things to the database. The theme_mods or option. How you do it is up to you. Now, let’s look at how to create a section, shall we? This too, like the previous two takes two arguments. A unique ID and an associative array.

$wp_customize->add_section( 'my_section', array(
	'title' => '', // the title of the section
	'description' => '', // description of the section
	'priority' => '', // the higher the number the lower in the customizer from the top
	'capability' => '', // default setting is 'edit_theme_options'
	'panel' => '', // if none it will show on main panel
	'active_callback' => '' // based on preview context
	) );

Simple and fairly straight-forward, right? What’s pretty cool too is that you can use the active_callback to your advantage. For example if you wanted to show a certain section only a widgetized area was being used. You could use a callback like:

// in the customizer
'active_callback' => 'widgetized_cb'
// later on in the code
function widgetized_cb(){
	return is_active_sidebar( 'primary' );
}

add_panel

Pretty awesome right? See where some of that logic can come into play? Great! Now you know how to add settings, controls, and sections. We can finally take a look at the final one: panels!

What’s super awesome is that this, too, uses two arguments. A unique ID and an associative array. Notice a pattern here? Let’s look at the available ones:

$wp_customize->add_panel( 'my_panel', array(
	'title' => '', // the title for the panel
	'description' => '', // short description of the panel
	'priority' = '', // the higher number, the lower from the top
	'active_callback' => '' // based on preview context
	) );

As you can see not a lot for the panels – yet. The customizer is constantly being worked on in core. There are a lot of things you can do to make it better if you want to help out.

Previewing

Okay, this is the part where things really come together because it deals with JavaScript. You remember in the add_setting there was an option for transport? If you want to create live previews without the entire page being refreshed, you set it to postMessage. In order for it to take place you will have to include a little JavaScript. I would highly recommend using a dedicated file for this. All you have to do is hook to the right place and enqueue it.

add_action( 'customize_preview_init', 'my_theme_preview' );
function my_theme_preview(){
	wp_enqueue_script( 'my-theme-js-preview-file', get_template_directory_uri() . '/js/my.customize.preview.js', array( 'customize-preview' ), '', true );
}

From there your JavaScript file would include something like:

wp.customize( 'setting_id', function( value ) {
	value.bind( function( newvalue ) {
		// do things
	} );
} );

Final thoughts

So there you have a slight crash course on how the customizer works and what options are available to create a good theme option user experience. There are a few little tricks and things you can also do, so go ahead and explore the core code and find out! You’ll be amazed at what you will find.

Fun with template tags: comment_form

This time I’ll focus on the comment_form(). Neat, fun and with plenty of hooks and filters.

The code

Like usual we will look at the core code of the comment_form. There are approximately 230 lines of code that make up this template tag. Does sound like a lot, right? Yes, but when you look a little closer it is the inline documentation that makes up the brunt of it all.

Yes, documentation. I love it and is what I am doing to an extent with these posts. I am documenting their use with examples in hopes that somebody finds it useful. I know at least one person will.

Anyway, back to the point. The hooks and filters.

The filters

One of the first filters is comment_form_default_fields. Pretty neat one because you can add, remove, and even edit form fields. Let’s make a quick edit and remove the website field from the default, shall we?

add_filter( 'comment_form_default_fields', 'my_new_fields' );
function my_new_fields( $fields ){
	$fields['author'] = '<p class="author input"><label for="name"><span class="required">Your name:</span></label><input name="name" type="text" /></p>';
	
	unset( $fields['url'] );
	return $fields;
}

Pretty neat, right? The next one that we come across is the comment_form_defaults. This one is a little more fun in that it has the previous one included with it. I know you may be thinking what do I mean by that, so let’s look at the code:

$defaults = array(
	'fields' => $fields,
	'comment_field' => '<p class="comment-form-comment"><label for="comment">' . _x( 'Comment', 'noun' ) . '</label> <textarea id="comment" name="comment" cols="45" rows="8" aria-describedby="form-allowed-tags" aria-required="true" required="required"></textarea></p>'

That $fields variable is from the previous filter. It is the line before the $defaults array is set. So much like the previous filter we can edit and remove from the default comment_form.

add_filter( 'comment_form_defaults', 'my_custom_form' );
function my_custom_form( $array ){
	$array['class_submit'] ='submit blue input';
	$array['title_reply'] = __( 'Drop us a line', 'text-domain' );
	$array['title_reply_to'] = __( 'Argue with %s', 'text-domain' );
	$array['cancel_reply_link'] = __( 'nevermind!', 'text-domain' );
	
	return $array;
}

From the above example you can see we change the submit class to include blue and input. A few other things were changed and the best part is that you can use a child theme to remove that or even add your own. That’s cool if you wanted to make a lot of additions or deletions but what if you wanted to do it to just one? That’s where

echo apply_filters( "comment_form_field_{$name}", $field ) . "\n";

comes into play. Where $name is the input you wanted to edit. For example:

add_filter( 'comment_form_field_author', 'my_new_author_field' );
function my_new_author_field(){
	return '<label for="author">' . __( 'What is your name, yo?', 'text-domain' ) . '<span class="required">*</span></label><input id="author" name="author" type="text" size="30" />';
}

Pretty cool if you have to change a few thing in order to properly style your form elements.

The hooks

Cool! Those were some of the filters but we cannot just leave without a few action hooks, right? I mean why wouldn’t you like action hooks? Those are so cool because you can add things conditionally.

Let’s look at some of them shall we? There are nine in total. Yes, 9. Not nine thousand. Just nine. That’s quite a few that we can hook to. Good! Plenty of things to mess and tweak with. Some of the neater ones I like are:

do_action( 'comment_form_before' );
do_action( 'comment_form_top' );
do_action( 'comment_form_before_fields' );
do_action( 'comment_form_after_fields' );
do_action( 'comment_form', $post_id );
do_action( 'comment_form_after' );

The reason I like the fifth one is because it is a dynamic one. You can add to the form depending on the post’s ID. Let’s say you wanted to add a note to all posts published before a certain date. You could potentially go through every single one but that could be time consuming. What’s nice is that WordPress uses an incremental ID meaning that when a new post is added it uses the next highest number for the ID. You could use something like:

add_action( 'comment_form', 'my_form_notice' );
function my_form_notice( $id ){
	if ( $id < 1155 ){
		printf( '<span class="notice">%s</span>', __( 'This post may be outdated', 'text-domain' ) );
	}
}

Do keep in mind that some of the above mentioned methods could be used for both plugins as well as themes so use them wisely.

Fun with template tags: comments_template

On my last post I talked about dynamic_sidebar and some uses. It was a fun little experiment I wanted to do and share. Yes, I said experiment. That is how I learn. I read, do and then share. I know I’m not the only one that does that.

This time I dabbled with comments_template(). Yes, another one of the more common template tags. I wanted to dissect the function and see what really makes it unique. Okay, not really, I more or less wanted to look at the code and see how it gets the template file.

Core code

The code itself is about 90 lines. That is including the inline documentation. Without the inline documentation it is about 60 lines. Good to know. It means we don’t have to guess what is going on a lot. So let’s dive in shall we?

Okay, let’s break the function down, shall we?

The arguments

The first argument that is passed is the $file location. The second is whether or not to separate the comments. Simple. But what does that mean and how can we change this?

One way, of course is by passing some arguments ourselves. Let’s say we wanted to separate the comments, we would use:

<?php comments_template( '', true ); ?>

Or if we had our comment template in another location we would use:

<?php comments_tempate( '/inc/comments.php' );

That’s great if your comment template resided in the inc folder and was named comments.php. But what happens if you don’t have a comments.php file anywhere in your theme’s folder? Well, the nice part is that WordPress does account for that. The downside is that it creates a deprecated_file call. Yes, an error. If you read the following doc-block you can see why.

/**
 * @package WordPress
 * @subpackage Theme_Compat
 * @deprecated 3.0
 *
 * This file is here for Backwards compatibility with old themes and will be removed in a future version
 *
 */

I’m going to emphasize the part that really matters most:

and will be removed in a future version

Backwards compatibility is one thing that WordPress does really well; though this is one time I wish it would do it faster. At least for these files. There are a few other files but I’ll focus on this for now.

But why does it load that file if there is no comments.php file? Let’s look a little closer at what the function actually does. At least the parts that really make it load the needed file.

if ( empty($file) )
	$file = '/comments.php';

$theme_template = STYLESHEETPATH . $file;

$include = apply_filters( 'comments_template', $theme_template );
if ( file_exists( $include ) )
	require( $include );
elseif ( file_exists( TEMPLATEPATH . $file ) )
	require( TEMPLATEPATH . $file );
else // Backward compat code will be removed in a future release
	require( ABSPATH . WPINC . '/theme-compat/comments.php');

Not really much code, right? First it checks if the passed argument $file is empty and if it is it creates a simple string of '/comments.php'. Then, it creates a variable $theme_template with the constant TEMPLATEPATH and $file appended to it. Next we see a fairly familiar function apply_filters(). The filter name is comments_template.

We can then use a filter hook to change the location of our comments template. Granted we can do the same without even using the filter by simply passing it the location string to the function itself as we saw above, right?

It matters

Why am I bringing this up? I am bringing this up because the comments template file should be the place to be using wp_list_comments() as well as comment_form(). It doesn’t have to be comments.php that houses those template tags. It could be named anything you want, you just have to make sure you are loading the file properly.

Using a filter

One way is using a filter hook. As you noticed above the line:

$include = apply_filters( 'comments_template', $theme_template );

This what we can use. The code would look a little something like:

add_filter( 'comments_template', 'demo_path_to_comments_template' );
function demo_path_to_comments_template( ){
	if ( is_child_theme() && file_exists( get_stylesheet_directory() . '/inc/coms.php' ) ){
		return get_stylesheet_directory() . '/inc/coms.php';
	} else {
		return get_template_directory() . '/inc/coms.php';
	}	
}

Yes, quite a bit just for comments, right?

Using an argument

What’s super cool about using the core template tag and passing it the argument is that it will first look in the child theme ( if active ) and then the parent theme for the file you designate.

<?php comments_template( '/comments/pings.php', true ); ?>

In the above example it will first look for the pings.php file of the child theme ( if it is active ) and if that file does not exist it will load the parent file. Sort of what get_template_part() does. That is another neat little function for another post.

Seriously, it matters

I’m going to repeat this part because it bears repeating. The backwards compatibility file will one day be removed. Your users will thank you for not using the fallback file. It shouldn’t be a safety net for the theme. Besides, if you want the theme to be hosted in the repository it can’t have any errors.

Fun with template tags: dynamic_sidebar

The last couple of weeks I’ve been reading the core code more and more. I like it. Came to the conclusion I really don’t know every hook or filter. I don’t claim to though. I like knowing enough to make a functional theme or even a plugin. Yes, I’ve been recently dabbling with one but that’s for another post.

The reason for this post is to share some knowledge. Hopefully somebody finds this useful or helpful.

The function

For this post I will be using dynamic_sidebar(). It’s a fairly common template tag in themes. It gets a widgetized area and outputs them in a designated area. In order for that to happen you must first have a registered area. We do that by using register_sidebar(). For demonstrational purposes we will use:

register_sidebar( array(
	'name'          => __( 'Footer Area', 'dademo' ),
	'id'            => 'footer-area',
	'description'   => __( 'Add widgets here to appear in your sidebar.', 'dademo' ),
	'before_widget' => '<aside id="%1$s" class="widget %2$s">',
	'after_widget'  => '</aside>',
	'before_title'  => '<h2 class="widget-title">',
	'after_title'   => '</h2>',
) );

Great! So we created a widgetized area with an ID of footer-area. It can be anything we want but we will currently stick to simple naming conventions. Now, let us look at the core code, shall we?

The core code

The function itself is quite a few lines of code. Approximately 160 lines. I’m not going to post all of that code. The developer reference page has it and you can even view on trac. The ones that matter most for this post are two lines.

The first line:

do_action( 'dynamic_sidebar_before', $index, true );

The second line:

do_action( 'dynamic_sidebar_after', $index, true );

Notice something a little strange about it? I’m referring to the $index part of course. This is the neat part of it all. What does that little part mean?

Our hook

The cool part is that you can hook to specific widgetized areas if you want. I know you may be asking what I mean by this so I’ll demonstrate a little bit. Take our previous example of footer-area above and we will wrap it within a <section> element tag with a class of row.

add_action( 'dynamic_sidebar_before', 'demo_sidebar_before' );
function demo_sidebar_before( $index ){
	if ( $index == 'footer-area' ){
		echo '<section class="row">';
	}
}
add_action( 'dynamic_sidebar_after', 'demo_sidebar_after' );
function demo_sidebar_after( $index ){
	if ( $index == 'footer-area' ){
		echo '</section><!-- Widgetized footer area -->';
	}
}

From there it would render:

<section class="row">
	<aside id="recent-posts-4" class="widget widget_recent_entries">
	<h2 class="widget-title">Recent Posts</h2>
	<ul>
		<li>
		<a href="/2015/04/13/aesop-testing/">Aesop testing</a>
		/li>
		<li>
		<a href="/2015/04/13/sampling-some-code/">Sampling some code</a>
		</li>
		<li>
		<a href="/2015/04/08/another-gallery/">another gallery</a>
		</li>
		<li>
		<a href="/2015/04/08/gallery-7/">gallery 7</a>
		</li>
		<li>
		<a href="/2015/04/08/gallery-6/">gallery 6</a>
		</li>
	</ul>
	</aside>
</section><!-- Widgetized footer area -->

As you can see it created the section element and inside of it is a simple recent posts widget. Now, as I mentioned that is for specific widgetized areas. The thing to remember is to use the ID of the widgetized area to conditionally add or remove. It is that $index that is used to test. You can add things to every single dynamic_sidebar call by not even checking. Let’s say we have two widgetized areas. One in the footer and the other just above the content. We will call that section, “content-above.”

I know, very creative. I said it would be simplistic, didn’t I?

Okay, we wanted to add few things. Let’s say we wanted to add an image to both of those sections. We could edit two different files depending on how your theme is structured. Sounds a little painful, right? So, we will use our handy-dandy little hook:

add_action( 'dynamic_sidebar_before', 'demo_sidebar_before' );
function demo_sidebar_before( $index ){
	echo '<section class="row">';
	echo '<img src="' . get_template_directory_uri() . '/img/divider.png" />';
}
add_action( 'dynamic_sidebar_after', 'demo_sidebar_after' );
function demo_sidebar_after( $index ){
	echo '</section><!-- Widgetized area with image -->';
}

Pretty cool, right? What’s super cool is it will render like:

<section class="row">
<img src="path/to/img" />
<!-- widgets -->

</section><!-- Widgetized area with image -->
<section class="content row">
<!-- the_content -->
</section>

<section class="row">
<img src="path/to/img" />
<!-- widgets -->
</section><!-- Widgetized area with image -->

Yes, all that markup where ever you are using dynamic_sidebar().

Advanced fun

This part I’m writing as my left eye is twitching only because it deals with widgets in themes. Yes, I’ve never liked including them. This part deals with hooking to particular widgets in your theme.

Yes, you could simply edit the file that has the widget but where is the fun in that? This time we will use an action hook.

add_action( 'dynamic_sidebar', 'demo_sidebar' );
function demo_sidebar( $obj ){
	
	if ( $obj['callback'][0]->id_base == 'meta' ){
		printf( '<span>%s</span>', __( 'So much meta', 'dademo' ) );
	}
	// Alternatively
	// if ( preg_match( '/meta-/', $obj['id'] ) ){
	//	printf( '<span>%s</span>', __( 'So much meta', 'dademo' ) );
	// }
}

Does look a little complex, right? Let’s break it down a little.

First, we create the hook in line 1. Then we create our callback function in line 2. Doing good so far. Line 3 is where it does get a little odd. What does it mean? What does it mean?!

Okay, it may look a little complex to some but I’ll explain a little bit more.

When using dynamic_sidbar() it uses an array for the widgets. If there are no widgets then the function returns a false value. If there are it creates an associative array of the widget instance. That array is what we pass our callback function. In the example it is called $obj. In that array we have a key called callback. It, too, is an array.

We are looking for the first item on there because it holds the important part. The information about the widget object. The example is looking for the id_base of the widget. You know that little part you named when you registered the widget.

The alternative uses preg_match to match the ID of the widget’s instance. Yes, you can do specific instances as well.

My gripe with widgets

Yes, I don’t like widgets. Okay that is not entirely true because I am using a few but it’s not what I’m referring to. What I’m referring to is when themes include widgets.

Themes that include widgets for contact forms, testimonials, group -or team- members of a company. Dare I say it? Newsletter widget. Cue dramatic music. Yes, I am referring to most of those. The reason I hate them is because you lose it once you switch a theme. It reminds me of the shortcut icons I see being used by a lot as well. It does drive me up a wall.

Up a wall, you say?

Yes. The reason for that is because there are dozens, and dozens of plugins that can do it and possibly do it better. Some things are not meant to change. The shortcut icon ( favicon ) should be one. In my opinion some widgets should be the same way. I make an exception only because I know there is at least one theme that unregisters core widgets and includes their own extended version of that widget. You still lose that functionality ( keyword right there ) once you make a switch to a new theme.

I know you may be asking and even wondering what argument, or arguments, could be made. Well, some people never change their themes. True. The thing to remember too is that even down the road they may just think about changing that theme. It will be a bad experience once they change that theme and lose the widget(s) they had.

There are some that are purely aesthetic and add to the theme’s experience but should that be the end all to turn to for widget design, functionality? I don’t know but it does seem a little strange that I haven’t seen many themes proclaiming support for certain widgets.

Start a trend

Yes, it would be nice. At least to see some theme authors supporting more and more plugins or specialized widgets. I mean after all that is what the description is for or even the theme’s documentation, right?

Why a theme’s changelog is important

Having some history is a good thing and knowing what changes were made and why is even better. That is one of the reasons that I love seeing a changelog when I look in a theme’s folder. Supposing they have one.

Not all themes are created equal

It’s true. When I speak of themes I generally refer to the themes submitted and maintained in the WordPress.org repository. I don’t mean those that you buy either. I don’t like to because I feel you pay for a certain level of not just support but dare I say care? I don’t know. Just two slightly different areas to me.

The reason I bring this up is because in the middle of making a change to my current project at hand I wanted to know why I chose to use a specific method and why it wasn’t working. At least on my working copy of the project. I tried to think back on what changes I had made and realized I hadn’t kept track of any changes; let alone major ones.

It reminds me a bit of history class. Military History to be exact. Yes, I took that class in high school. It was fun and a neat class to take. I learned a bit about why you use certain strategies and when. Kind of see where I’m getting at? Tactics, planning and thinking ahead were all at play. I just didn’t really think about it at the time. That and documentation. I didn’t do that part.

A little flashback

Over a year ago I came across two trac tickets. #45 on the WordPress meta side and #22810 on the core side. The downside is that is hasn’t had a lot of attention. ( That needs to change ). Personally I think it is a step in the right direction for themes. Users, end-users and developers alike. The reason is of course to keep track of what changes were being made and why. A good thing to look at and know so things won’t break and if they do you’ll have an idea of why and what to look for.

A good example is WordPress core itself. If you checkout the timeline it shows you what changes ( if you look at the changesets ) are made to the project itself. It’s a great reference point to keep if something breaks down the road. One reason I’ve liked using some form of version control is because of that.

Many themes I’ve come across could benefit from this because they make a lot of changes.

A long road ahead

Yes, there is a lot to be done when it comes to themes and better practices. I think a changelog is good one to have. It’s a lot easier when you are using a version control system. Just append the commit message to the file and you have your changelog. Do keep in mind that is one way of doing it, there are others.

I think this may be the bigger hurdle to get over. The formatting of said changelog. I’ve seen more and more that link to a github repository of all the commits, which can be good if you have an internet connection and a reliable one at that.

If you feel like that changelog needs to happen then please go and comment on the tickets. Create a patch. Do something about it.