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.

Filtering the page links

Nothing is ever truly perfect. There are some things that do come close though. In the mean time we can make just a few changes to get our desired result. The photo above is a quick comparison of a photo I took a few years back while at Yosemite National Park.

As you can see there is a huge difference between the two. One is more vibrant and full of color while the other is just a little flat with little to no contrast. Yeah, I critique my own photos constantly. The left is the raw untouched file taken with my camera and the right is the edited version. As you can see it made it better by correcting some color and adding a little more light to the overall image.

Now, in WordPress one way of altering is by using filters. Recently I’ve been messing with one in particular that I feel can be a good practice for any theme developer. Filtering the arguments of wp_link_pages() to style post pagination.

Pagination?

Yes, pagination in posts. Often times when a tutorial or a written work is far too long that it needs to be divided into segments of easy to read, easy to consume blocks of text. In WordPress the

<!--nextpage-->

tag is used in the text editor to create another page within that post. WordPress handles this in one of two ways. The first is by listing the pages and the other is by using simple next/previous links. All themes tend to style that in different ways. The default Twenty Thirteen handles it like:

twenty-thirteen-link-pages.PNG

The way it is styled uses the same code throughout all the content related files. The reason I say it that way is because 2013 has support for all the post formats available within WordPress, which is amazing! Now the downside to that is that it can mean you have to copy/paste, type out a lot more code than you’d want to. I know I can be that way. I just want to be able to set it once and be done. I mean who doesn’t, right?

So, the way 2013 is coded is by calling wp_link_pages and then passing to it an array with some settings.

 wp_link_pages(
        array(
                'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentythirteen' ) . '</span>',
                'after' => '</div>',
                'link_before' => '<span>',
                'link_after' => '</span>'
        ) );

As you can see you would copy and paste that code on all the files depending on how you have all your content files setup. While it does create that nice little HTML structure for us to style it may be tedious to have to copy and paste over and over. I know I got tired of it.

Solution

What I did was looked at the source code for the function. I took notice at one particular line of code that made me happy. That line was:

$r = apply_filters( 'wp_link_pages_args', $r );

The reason it made me happy was because I realized that I could filter the arguments and not have to type out all that code over and over again or even have to copy and paste it all. So all I now had to do was create a callback function and hook it through a filter.

add_filter( 'wp_link_pages_args', 'theme_link_pages_args' );
function theme_link_pages_args( $args ){
    $args = array(
        'before'           => '<div class="link-pages">Page ',
        'after'            => '</div>',
        'link_before'      => '',
        'link_after'       => '',
        'next_or_number'   => 'number',
        'separator'        => '<span>',
        'nextpagelink'     => 'Next Page',
        'previouspagelink' => 'Previous Page',
        'pagelink'         => '%',
        'echo'             => 1
    );
    return $args;
}

*If you are going to filter the $args make sure you use all the settings or you may end up getting some errors.

There we have it! Keep in mind that if you want the theme to be translation ready don’t forget to add the proper functions where needed and prefix the function with your theme’s name.