WordPress 3.0 has something very handy that I want theme authors to start implementing as soon as possible.
To show exactly why it’s so useful, I modified my own theme to start using it.
Demonstration
So, here’s a big hunk of code I pulled out of my current theme’s comments.php. This hunk of code has only one purpose: To display the form area where people can leave a comment:
<?php if ('open' == $post->comment_status) : ?> <div id="respond"> <h3><?php comment_form_title( 'Leave a Reply', 'Leave a Reply to %s' ); ?></h3> <div class="cancel-comment-reply"> <small><?php cancel_comment_reply_link(); ?></small> </div> <?php if ( get_option('comment_registration') && !$user_ID ) : ?> <p>You must be <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?redirect_to=<?php echo urlencode(get_permalink()); ?>">logged in</a> to post a comment.</p> <?php else : ?> <form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> <?php if ( $user_ID ) : ?> <p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo wp_logout_url(get_permalink()); ?>" title="Log out of this account">Log out »</a></p> <?php else : ?> <p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" size="22" tabindex="1" /> <label for="author"><small>Name <?php if ($req) echo "(required)"; ?></small></label></p> <p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="22" tabindex="2" /> <label for="email"><small>Mail (will not be published) <?php if ($req) echo "(required)"; ?></small></label></p> <p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" /> <label for="url"><small>Website</small></label></p> <?php endif; ?> <!--<p><small><strong>XHTML:</strong> You can use these tags: <code><?php echo allowed_tags(); ?></code></small></p>--> <p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p> <p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" /> <?php comment_id_fields(); ?> </p> <?php do_action('comment_form', $post->ID); ?> </form> <?php endif; // If registration required and not logged in ?> </div> <?php endif; // if you delete this the sky will fall on your head ?>
Nasty, eh? It’s a mess of if/else statements. It handles cases where the user is logged in or not, where the comments are open or closed, whether registration is required, etc. It’s confusing, difficult to modify, poor for CSS referencing…
Here’s what I replaced all that code with:
<?php comment_form(); ?>
Now then, that’s much better, isn’t it?
The comment_form function is new to 3.0. Basically, it standardizes the comments form. It makes it wonderful for us plugin authors, since now we can easily modify the comments form with various hooks and things. I’ve already modified Simple Facebook Connect and Simple Twitter Connect to support this new approach; if you’re using a theme with this, then the user won’t have to modify it to have their buttons appear on the comments form.
Customizing
Since theme authors love to customize things, the comments form is also extremely customizable. Doing it, however, can be slightly confusing.
Inside the comments_form function, we find some useful hooks to let us change things around.
The first hook is comment_form_default_fields. This lets us modify the three main fields: author, email, and website. It’s a filter, so we can change things as they pass through it. The fields are stored in an array which contains the html that is output. So it looks sorta like this:
array( 'author' => '<p class="comment-form-author">...', 'email' => '<p class="comment-form-email">...', 'url' => '<p class="comment-form-url">...' );
I truncated it for simplicity. But what this means is that code like this can modify the fields:
function my_fields($fields) { $fields['new'] = '<p>Some new input field here</p>'; return $fields; } add_filter('comment_form_default_fields','my_fields');
That sort of thing lets us add a new input field, or modify the existing ones, etc…
But fields aren’t the only thing we can change. There’s a comment_form_defaults filter too. It gets a lot of the surrounding text of the comments form. The defaults look sorta like this:
$defaults = array( 'fields' => apply_filters( 'comment_form_default_fields', $fields ), 'comment_field' => '<p class="comment-form-comment">...', 'must_log_in' => '<p class="must-log-in">...', 'logged_in_as' => '<p class="logged-in-as">...', 'comment_notes_before' => '<p class="comment-notes">...', 'comment_notes_after' => '<dl class="form-allowed-tags">...', 'id_form' => 'commentform', 'id_submit' => 'submit', 'title_reply' => __( 'Leave a Reply' ), 'title_reply_to' => __( 'Leave a Reply to %s' ), 'cancel_reply_link' => __( 'Cancel reply' ), 'label_submit' => __( 'Post Comment' ), );
All the various pieces of html that are displayed as part of the comment form section are defined here. So those can be modified as you see fit. However, unlike the fields, adding new bits here won’t help us at all. The fields get looped through for displaying them, these are just settings that get used at various times.
But filters are not the only way to modify these. The comment_form function actually can take an array of arguments as the first parameter, and those arguments will modify the form. So if we wanted a simple change, like to change the wording of “Leave a Reply”, then we could do this:
<?php comment_form(array('title_reply'=>'Leave a Reply, Stupid')); ?>
This gives us a simple and easy way to make changes without all the trouble of filters. Nevertheless, those filters can be very useful for more complex operations.
But wait, there’s more!
As the comments form is being created, there’s a ton of action hooks being called, at every stage. So if you want to insert something into the form itself, there’s easy ways to do it.
A quick list of the action hooks. Most of them are self-explanatory.
- comment_form_before
- comment_form_must_log_in_after
- comment_form_top
- comment_form_logged_in_after
- comment_notes_before
- comment_form_before_fields
- comment_form_field_{$name} (a filter on each and every field, where {$name} is the key name of the field in the array)
- comment_form_after_fields
- comment_form_field_comment (a filter on the “comment_field” default setting, which contains the textarea for the comment)
- comment_form (action hook after the textarea, for backward compatibility mainly)
- comment_form_after
- comment_form_comments_closed
CSS and other extras
Let’s not forget styling. All parts of the comments form have nice classes and id’s and such. Take a look at the resulting HTML source and you’ll find all the styling capabilities you like. Also, everything is properly semantic, using label tags and aria-required and so forth. All the text is run through the translation system for core translations.
So theme authors should start modifying their themes to use this instead of the existing big-ugly-comment-form code. Your users will thank you for it. Plugin authors will thank you for it. And really, it’s about time we made WordPress themes more about design and less about the nuts and bolts of the programming, no?
SFC 1.0 – FB Comments Integration
Added a new feature that people have been asking me for since I created SFC to begin with: Comments Integration.
Facebook comments
When you make a post with SFC, the publisher plugin has the ability to push that post to either your Facebook Page or Profile. Up until now, the auto-publish feature has been doing this and storing meta-data with the post about the resulting “story” id that Facebook sends back. This data was stored, but not really used.
No longer. Now, if you auto-publish to Facebook, you have the option to pull comments back from that automatically published Facebook post and show them in the blog as if they were normal WordPress comments.
You can see this in action here on my own site. On the SFC 1.0 Photo Support post, you’ll find a comment at the bottom made by a user named “Kartsios Vasilis”. That comment wasn’t left here on this site, it was left on the Facebook story corresponding to that post. As you can see, the avatar for the user shows up on the comment, it’s styled differently (I felt the blue background sort of distinguished it), and it doesn’t have a reply link.
Since these aren’t “real” WP comments, and don’t live in the WP database, you can’t reply to them properly. So the reply link is automatically removed for them. I used a styling rule in the CSS to add the “This comment was originally made on Facebook, so replying to it here is not allowed.” message where the Reply link would normally be. Because this is just using a simple CSS style rule, you can make that message anything you like, or not have it at all. That’s up to you and your theme.
The new feature is relatively painless too. No configuration is needed. Every 6 hours (minimum), the plugin will retrieve the relevant comments from the Facebook posts, then store them as a transient. This reduces the amount of work since it doesn’t have to talk to Facebook every time. The comments are then integrated in with the normal comments for the post, and the comment count is updated to reflect the right number.
There’s still some minor detail work to be done.
Right now, for example, the comments are just added onto the end of the list of comments, and so they’re out of order. The final version will have the comments integrated in correctly by the date and time they were made. Edit: This is now working, comments are added in the proper order.If you want to use the beta version of SFC (currently marked as version 0.999) you can find it in the WordPress Plugins SVN repository.
Edit: The CSS to add this text, since people asked, is this:
Simple, really.
Category: Code, Other | 21 Comments