Quick n’ Dirty Spam Protection
Thursday
Jan 31, 2008

This is the eighth of my Quick N Dirty plugin posts and today the plugin has no hooks at all. The plugin I am explaining today helps to prevent automated spam and is something I have been using on my blog since I started it.
So far, every plugin I have explained has had either an action or a filter to trigger the functionality. The point of each hook is that it lets you intervene in existing functions. In this case however the plugin doesn’t need to do that.
I need the plugin to run some code as soon as it is loaded, which means I simply put the code in plugin file and don’t wrap it in a function, and I need part of it to run at specific points inside the comment form, so I provide a function for that.
To get the plugin working you need to do two things: first install the plugin, second make some changes to you comment form. The following example shows how the function in the plugin should be used:
<?php $time_value = time(); ?> //you only need this once in your template <label for="<?php qnd_useFormField('url' , $time_value );?>"><small>Website</small></label> <input type="text" name="<?php qnd_useFormField('url' , $time_value );?>" id="<?php qnd_useFormField('url' , $time_value);?>" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" />
This code shows a label and the name field. I have used the same function multiple times in the for field of the label, the name and id fields of the textbox.
The first parameter is the old name of the form, in the case url. The second parameter is a variable containing the current time. Notice though that because the function is being used several times the time value needs to be the same each time, so we set the value of the variable once. It will not work properly if you include time() directly in the function call.
You need to do this for all the form fields in the comment form; although the time variable only needs to be set once for the entire form.
So what does it do. Well here is the plugin code, I will explain it below:
<?php /* Plugin Name: Quick n' Dirty Spam Protection Plugin URI: http://www.wp-fun.co.uk/2008/01/27/quick-n-dirty-spam-protection/ Description: Provides a facility for randomising the names of form fields Author: Andrew Rickmann Version: 0.1 Author URI: http://www.wp-fun.co.uk */ //make sure that a session has started so that we store //information in the session if ( session_id() == "" ){ session_start(); } //limit the replacements so that no other forms are affected. //wp-comments-post is where comments go to be processed if ( $_SERVER['PHP_SELF'] == '/wp-comments-post.php' ) { //if we have previously set the session variables //then load them, otherwise just load an array; if ( isset( $_SESSION['qnd_formFields'] ) ) { $qnd_form_fields = $_SESSION['qnd_formFields']; } else { $qnd_form_fields = array(); $_SESSION['qnd_formFields'] = array(); } //when the session variable is created the name of the //original field is the array key, and the random variable //is the value. foreach($qnd_form_fields as $key => $value){ if ( isset($_POST[$value]) ) { $_POST[$key] = $_POST[$value]; unset($_POST[$value]); } elseif ( isset($_POST[$key]) ) { unset($_POST[$key]); } } } //this function allows us to set the session variable //in the html page. So we replace the name of each form field //with this function function qnd_useFormField( $name , $time ){ //write to the session variable. //create a random number and convert it to a hexidecimal number if ( !isset($_SESSION['qnd_formFields'][$name]) || $time != $_SESSION['qnd_formFields']['time'] ) { $_SESSION['qnd_formFields'][$name] = dechex(rand(0,429496729)); $_SESSION['qnd_formFields']['time'] = $time; } //output the number echo $_SESSION['qnd_formFields'][$name]; } ?>
The first thing the plugin does is make sure a session has been started as the plugin saves information in a session variable that is essential for it to work.
When the function is called it adds an entry to the array stored in the session variable, the index is the name of the form field, and it creates a random hexadecimal number for the value of the array entry.
If you load your page and view the source you will find that the form fields now have solely numeric names instead of the previously descriptive names.
The time variable I mentioned before the plugin makes sure that the value changes each time the page is loaded.
When you submit the form the bulk of the code runs automatically. First it checks to make sure that the page the plugin has been loaded on is the the comment handler. This makes sure we don’t mess with any of the form fields for any other forms that you might use on your blog, like the login or contact forms.
Next it retrieves the array from the session that contains the form names. This array is compared to the values that have been submitted in the $_POST variable, i.e. the form fields that have sent data to this page. If a submitted field matches one of the random values stored in the array it replaces this information with the original name of the form field.
If a field with one of the original names has been submitted; for example, if a form field with the name url has been submitted then it will be deleted as we know that value couldn’t have come from our form.
Once the values have been switched WordPress can process the comment in the normal way.
Why does this work?
Randomising the form names means that spambots cannot simply send the default form names to the form handler and expect them to be dealt with. The sessions mean that even if they read the page content and obtain the form names then there is every chance that the form names will have changed again when the bot sends their content.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Quick n’ Dirty Comment Stats
Wednesday
Jan 30, 2008

This is plugin number 7 in my Quick N Dirty plugin series and things are now starting to get a little more complex, and a little more interesting. In this post I will demonstrate an admin page for displaying stats.
Creating an admin page is actually a two stage process involving one hook and one function. We also need a function to actually output the content of the page. This means there are two functions this time, not three.
This hook this plugin uses is an action called: admin_menu. This is called when the admin menu is being constructed and that lets us run commands to add pages to the menu.
This where the first function comes in. As with all the earlier plugins the hook calls a function. This function adds a link to the admin menu. The admin menu link will contain parameters that tell the admin system to load this plugin file, and specifically, to run our second function. The second function contains all the logic and content for the actual page.
Effectively we have a chain: Action -> Function 1 -> Function 2
This plugin might look more complicated than the others but most of the complexity comes from the fact that I have used Google Charts to display the data.
If you were happy to simply print out the data, or create a series of div tags with a length set according to the value then it may be a little easier but the options available and the quality produced by Google Charts makes it worthwhile in my opinion. I won’t be explaining in detail how Google Charts works. The plugin puts together a list of variables in a URL and uses that as the src attribute for a normal image. If you want to look more into what the various parts of the Google Charts URL you can find the details on the Google Charts API Page.
<?php /* Plugin Name: Quick n' Dirty Comment Stats Plugin URI: http://www.wp-fun.co.uk/2008/01/27/quick-n-dirty-comment-stats/ Description: Adds a statistics page to the comments section and displays some basic information Author: Andrew Rickmann Version: 1 Author URI: http://www.wp-fun.co.uk */ //This is the line that adds your filter into the list. // 'admin_menu' is the name of the filter // 'qnd_create_comment_stats_menu' is the name of the function, below add_filter( 'admin_menu' , 'qnd_create_comment_stats_menu' ); function qnd_create_comment_stats_menu(){ //this function only calls one comment, the comment that creates the submenu page add_submenu_page( 'edit-comments.php' , //the parent page that the submenu will be below 'Quick n\' Dirty Comment Stats' , //the page title 'Stats' , //the title displayed on the menu 8 , //the security level 0 = lowest 10 = highest __FILE__ , //the file where the page can be found (this one) 'qnd_output_comment_stats_page' ); // the function that outputs the page (below) } function qnd_output_comment_stats_page(){ //do any processing that must be done before the page is loaded //get information here, or process post variables submitted from a form //start to put together the url needed for google charts $chart_base_uri = 'http://chart.apis.google.com/chart?chs=650x200&cht=bvg&chxt=x,y'; $chart_posts_addition = '&chtt=Comments%20on%20the%20last%20twenty%20posts'; //get posts, only using the last 20 for example purposes $posts = get_posts('numberposts=20&orderby=post_date&order=ASC'); //create an array to hold the number of comments and post ID $comment_array = array(); $post_title_array = array(); //assign each value to the requesite array foreach($posts as $post){ $comment_array[] = (int) $post->comment_count; $post_id_array[] = (string) $post->ID; } //change the scale to use the full height of the graph $maxca = max( $comment_array ); $scale = 100 / $maxca; //apply to scale to each comment count for($i = 0 ; $i < count($comment_array) ; $i++ ){ $comment_array[$i] = $comment_array[$i] * $scale; } //update the URL to contain the appropriate range of values (y axis) $chart_posts_addition .= '&chxr=' . '1,0,' . $maxca; //add the values, and the label for the x axis to the URL $chart_posts_addition .= '&chd=t:' . join( ',' , $comment_array ) ; $chart_posts_addition .= '&chxl=0:|'.join( '|' , $post_id_array ) ; //use the string to generate a google chart url //output the page itself ?> <div class="wrap"> <h2>Quick n' Dirty Comment Stats</h2> <img src="<?php echo $chart_base_uri . $chart_posts_addition;?>" alt="" /> </div> <?php } ?>
Here is an image showing the result on my test system:

I hope most the comments on the plugin above do most of the explaining, if they don’t, or you have any related questions just throw in a comment below and I will add to the description.
I think the important point to note is that most of the code involves changing the data so that it will meet the requirements for the Google Charts URL. The code that actually creates the page is simple, there is one command that adds the link to the menu and one hook as in the rest of the plugins so I hope you can see that creating admin pages is actually very easy.
If you feel the desire to expand this you might want to consider a pie chart showing how your posts are divided amongst your categories or a chart showing which pages were most commented on over the past month.
Tomorrow I’m going to demonstrate an antispam technique that, so far has not let a single spambot comment through on my own blog (so far, touch wood).
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Quick n’ Dirty Admin Login Screen
Tuesday
Jan 29, 2008

This is the sixth of my Quick N Dirty plugin posts and I am doing something different today; I am going to explain a plugin created by someone else.
The plugin I want to focus on today is the bm_custom_login plugin. This plugin allows you to replace your WordPress login screen with something a little more branded, and is a brilliant demonstration of just how easy it can be to produce a plugin.
Just like all the plugins in this series this uses only one hook, and actually has even less code than I have used so far.
The hook is uses is: login_head
add_action('login_head', 'bm_custom_login');
This action fires in the HTML head of the login page allowing you to add any CSS, or Javacript files you want to. The plugin outputs only one line of HTML, but the effects are significant. Here is the function it calls:
function bm_custom_login() { echo '<link rel="stylesheet" type="text/css" href="' . get_settings('siteurl') . '/wp-content/plugins/bm-custom-login/bm-custom-login.css" />'; }
It links to a CSS file in the plugin folder that points the login screen towards the custom images in the plugin folder.
I won’t reproduce any more of the plugin here, I encourage you to download a copy from the Binary Moon site and take a look at it. It has everything you need, the plugin, the CSS file and a template image to help you produce your own.
My version is on the left.
Tomorrow I am going to start looking at how plugins link in to the admin pages themselves. I will be demonstrating a plugin to create an admin page and display information on it.
Quick n’ Dirty Bookmark Navigation
Monday
Jan 28, 2008

This is the fifth of my Quick N Dirty plugin posts and it is a little more involved than the previous four. It isn’t any more difficult, in fact it is a very simple plugin, but it does require adding a tag to your theme, and adding some categories to your bookmarks. None of this is difficult though so I don’t foresee many problems.
In this post I am going to show you how you can use the blogroll functionality, and a small plugin, to create a fully controllable menu for your website. Now, by fully controllable I mean that you can move items about within the menu, set the links in any way you please and choose what links you display to normal visitors and what links you display to users that are logged in.
So how do you do this? I will go through it in steps; but before I start I should mention that this may not work on versions of WordPress below 2.3.
Step 1
The first thing you need to do is to log into your blog, choose blogroll, and create two new categories. The first is a list of links that you want every visitor to see, and the second is a list of links you only want users that are logged in to your website to see. Now note down the ID of each category. (In my example 15 is for all visitors, and 16 is for logged in users)
You should now create at least one link in each. Note that in the advanced panel there is a rating option. We will use this later on.
Step 2
Before we worry about the plugin you need to insert the list into your template. To do this you need to use the template tag: wp_list_bookmarks. The example below will create a pure list, without any titles, and will order it according to the rating field that I mentioned earlier.
<ul> <?php wp_list_bookmarks('category=15&categorize=0&title_li=0&orderby=rating'); ?> </ul>
Notice that I have given it category 15, the category ID that is available to everyone. You need to replace this with your category ID.
Also note that the rating field only allows you to rate from 0 to 9 so if you will have more lists than this you might want to use the notes column instead.
The plugin is going to insert the links that are assigned to category 16 automatically, so when you are rating your links, if you want a member only link to appear at a given point in the list you should leave that blank in the all user list; for example, if you want the first five links to be from the all-user list, rate them 1-5 in the order you want them. If you want the sixth link to be from the logged-in-only list then find that link and rate it 6, you can then rate your next all-user link 7 to continue the list.
None of this will matter though until the plugin is added.
Step 3
The plugin uses a filter: get_bookmarks. This is called whenever a request for a list of bookmarks is put in. If the request is only for the all-user list then the plugin checks to see if the user is logged in, and if the user is logged in automatically adds the logged-in-only links to list.
Here is the plugin:
<?php /* Plugin Name: Quick n' Dirty Bookmark Navigation Plugin URI: http://www.wp-fun.co.uk/2008/01/28/quick-n-dirty-bookmark-navigation/ Description: Adds a specified bookmark category to a list if the user is logged in. Author: Andrew Rickmann Version: 1 Author URI: http://www.wp-fun.co.uk */ //This is the line that adds your filter into the list. // 'tget_bookmarks' is the name of the filter // 'qnd_bookmark_navigation' is the name of the function, below // 1 is the priority, 1 being highest, and 10 lowers // 2 is the number of arguments the function expects to recieve. add_filter( 'get_bookmarks' , 'qnd_bookmark_navigation' , 1 , 2 ); function qnd_bookmark_navigation( $bookmarks , $options ){ //first we set our category id numbers. $normal_nav_id = '15'; //change this one to match your all-user list $member_nav_id = '16'; //change this one to match your logged-in-only list. //to make sure that we don't trigger an infinite loop //if we are in the admin screen, or asking for any category(ies) except //the all-user category we pass back the bookmarks and escape. //The bookmarks must always be passed back or else no list will appear at all. if ( is_admin() || $options['category'] !== $normal_nav_id ) { return $bookmarks; } //if the user is logged in and the requested category is all-user: if ( is_user_logged_in() && $options['category'] === $normal_nav_id ) { //change the list options so that we are requested the additional category $options['category'] = $normal_nav_id . ',' . $member_nav_id; //regenerate the list with both the categories included $bookmarks = get_bookmarks($options); //send them on their way. return $bookmarks; } } ?>
I hope it should be fairly clear what is going on in this plugin, after all it is very simple, but feel free to ask any questions you’re not sure about.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Suck My Knee Muddy Funkster
Monday
Jan 28, 2008
Problogger has an interesting post about swearing on blogs, so I’ve decided to take this opportunity to outline my thoughts on it.
I have read a few blogs with a lot of swearing and everytime I have it has felt like a gimmick; a Roy Chubby Brown or Andrew Dice Clay (Both with three names oddly enough) style wallow in obscenity that honestly added little, if anything, to the point of the converstation.
Certainly there are times where a bit of effing and jeffing is the most effective way to convey the anger that the blogger feels, and I think that those occasional outbursts are entirely reasonable, provided they are just really occasional. In those cases the swears are punctuation; they are the verbal equiavlent of just letting loose and breaking something and all the more powerful for being a once off.
The only time I find swearing offensive is if it is gratuitous. It is usually accompanied by personal attacks, or other failures of reasoning and I have, on all occasions, relagated those blogs to my do-not-read list. They do often seem popular though, especially those that choose public, or political figures as their targets.
I can’t recall a time when I have wanted to swear, or felt the need to express that much anger, in a blog post. I do know that I haven’t suffered the problems that some bloggers have, themes or logos being ripped off, plugins being hosted without their knowledge etc, that might drive someone to want to vent. I probably couldn’t say for sure until the situation arose but I don’t think I would resort to profanity even then.
At the very least I would let the post sit for a while before publishing and, probably, edit it later, in a calmer frame of mind.
I have been lucky that thus far comments on this blog have been clean, but I would take it as a duty to anyone that might visit this blog to clean up any coments that were unsuitably vivid.
I’m not sure you could call it reader appreciation as such, but I don’t see the need for a WordPress blog to feature unsavoury language, and I imagine it may come as a shock to some people to find it here, so I would switch it out before allowing the comment through.
Quick n’ Dirty Feed Footers
Sunday
Jan 27, 2008

This is the fourth of my Quick N Dirty plugin posts. In the first I used the the_content filter to repeat the links used in a post, at the end of that post. In this post I am going to the_content again, but this time I am specifically using it in place of another filter that could get you quite confused.
It is a pretty common thing to do these days, add a footer to each post in your feed. There are a few plugins that not only let you do it but give you a handy admin page to alter the content as well. Nothing beats knowing how to do it yourself though.
If you are going to do it yourself, there is one area that provides some confusion. There is a filter that sounds like it should be used, but simply won’t work for you. That filter is the_content_rss.
The problem is that the_content_rss is used in rss, and rdf feeds, but importantly not in the rss2 feeds which is what we all tend to use these days. So if you want to change the content of your feeds, for the moment at least, you need to use the_content and check to see whether a feed is being requested. Luckily this is very easy.
Here’s the plugin:
<?php /* Plugin Name: Quick n' Dirty Feed Footers Plugin URI: http://www.wp-fun.co.uk/2008/01/27/quick-n-dirty-feed-footers/ Description: Adds content to the bottom of each rss2 post Author: Andrew Rickmann Version: 1 Author URI: http://www.wp-fun.co.uk */ //This is the line that adds your filter into the list. // 'the_content' is the name of the filter // 'qnd_feed_content' is the name of the function, below add_filter( 'the_content' , 'qnd_feed_content' ); function qnd_feed_content( $content ){ //make sure that a feed is being requested if ( is_feed() ) { //create a string containing the html we want to add to the bottom $additional_content = '<div style="border:1px solid #ccc; padding:5px; background-color:#DBD2DC">'; $additional_content .= '<h2 style="margin:0 0 5px 0; font-size:95%; color:#AC26A7">Interesting Message</h2>'; $additional_content .= '<p>The content of the interesting message</p>'; $additional_content .= '</div>'; //return the content, and the additional content to WordPress return $content . $additional_content; } else { //if we are not within a feed just send back the original content return $content; } } ?>
I have used a basic WordPress tag - is_feed() - to check if a feed is being accessed. Once known the content can be modified. Very important, as with previous plugins is to return the content without changes if it is not a feed. As this is a filter, if no content is returned then no content will be displayed on screen.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Quick n’ Dirty Post Exclusion
Saturday
Jan 26, 2008

This is the third of my Quick N Dirty plugin posts. In the second post I showed how to access the post object and alter the post content before saving it back to the database. This plugin will also access to the post object, but this time I will use it to exclude posts from being displayed on the home page.
The hook I am going to use for this plugin is the_posts filter. This filter is called when a list of posts is pulled from the WordPress database ready to be displayed on screen.
The filter passes an array of post objects to the function which gives us the opportunity to carry out mass edits, add posts, or, as in this case, remove posts in certain circumstances.
What I want to do is to make sure that posts in my General category do not appear on the home page. I want them as part of my feed, as an added sweetener for subscribing, and I want them as part of my single post and my archives.
Here’s the plugin, I will explain more at the bottom:
<?php /* Plugin Name: Quick N Dirty Post Exclusion Plugin URI: [insert the plugin uri here] Description: Removes posts from the home page Author: Andrew Rickmann Version: 1 Author URI: http://www.wp-fun.co.uk */ //call the filter //the_posts is called when a list of posts is retrieved from the database //qnd_post_exclusion is the function //1 is the priority, 1 runs first, 10 last add_filter('the_posts', 'qnd_post_exclusion' , 1 ); function qnd_post_exclusion( $posts ){ //only apply this if we are looking at the home page if ( !is_home() ) { return $posts; } //create an array to hold the posts we want to show $new_posts = array(); //loop through all the post objects foreach( $posts as $post ){ //for each object get an array of applicable categories $cats = get_the_category( $post->ID ); //create a variable that determins if this post should be included //the default is true, i.e. include the post $include = true; //loop through all the categories applicable to the post foreach( $cats as $cat) { //if the post is assigned to our undesirable category then do not include it if ( $cat->name == 'General' ) { $include = false; } } //if we want to include it then add the post object to the new posts array if ( $include === true ) { $new_posts[] = $post; } } //send the new post array back to be used by WordPress return $new_posts; } ?>
By now the add_filter function should be fairly familiar so I won’t dwell on it. It shows the the hook, the function to be used, and specifies that it should run with the highest priority. I have chosen high priority so that any plugins that follow on that might modify the content of the post are saved the trouble of modifying a post that will later be removed. Aside from that the priority isn’t too relevant here.
The usual template functions is_home, is_feed, is_archive, etc will work at this point and so I have used is_home to restrict the plugin to posts displayed on the home page. If we are not dealing with the home page then the function will simply return the original array of posts. It is essential that it does return the array. Not returning the array is the same as filtering out every post, leaving no posts at all.
When the function is called it is passed an array of post objects. We use the post ID in each case to get an array of the categories the post is assigned to using the function below:
get_the_category( $post->ID );
We then iterate through this array and if our chosen category is not in the array for each post we add the post to a new array . When we are done it is this array that is passed back to WordPress to continue its journey toward screen.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Quick n’ Dirty Replacement Text
Thursday
Jan 24, 2008

In the first of my Quick N Dirty plugin posts I showed you an example of modifying the content of a post just before it is displayed on screen. In this, the second of the Quick n’ Dirty plugins I am going to look at modifying the text of a post before it is saved to the database.
Yesterday’s plugin used a filter (the_content) to modify the content coming out of the database. The problem with this approach is that it needs to be calculated every time the page is loaded. This can slow down the loading process which in turn affects your readers. Especially if there are a number of plugins filtering the content one after the other.
For more fundamental content changes it is better to do it just once, and to do it where the only affected user is yourself.
Instead of a filter, this time the plugin will use an action: wp_insert_post. wp_insert_post is triggered whenever the post content is sent to the database. Importantly, it is triggered after the content is sent, so it isn’t enough to modify the content, the plugin also needs to update the database, or call a function that does it for us. Thankfully there is such a function so it is a simple process.
This action passes two variables to our function, the ID of the post, and a post object. The post object is quite a useful one to get to grips with as it is used wherever WordPress interacts with a post. You can also access it directly from within a theme (inside the loop). For now we will take this as a variable, modify the content portion of it, and pass it on to another function.
What this all means in real terms is that this plugin will be triggered whenever you save, save and continue, or publish a post. It will take your content and replace the terms such as -wp-, that you could use in your post to save time, with the full word, in the case the word is ‘WordPress&rsquo. You can see the replacements that will be made in the array within the plugin itself.
Here is the plugin:
<?php /* Plugin Name: Quick N Dirty Replacements Plugin URI: [insert the plugin uri here] Description: Alters pre-defined terms within your post when the post is saved Author: Andrew Rickmann Version: 1 Author URI: http://www.wp-fun.co.uk */ //call the action //wp_insert_post is called for any post content update //qnd_replacement is our function //10 is the priority, 1 runs first, 10 last //2 is the number of arguments we want. //the default number of arguments is 1, just the ID. add_action('wp_insert_post', 'qnd_replacement' , 10, 2 ); function qnd_replacement( $post_ID , $post = NULL ){ //check to see if we have post information //if not then there is no point in continuing if ($post == NULL) {return;} //define an array to contain all our replacement values $replacement_array = array(); //set the full text replacements $replacement_array[] = array( '-css-' , 'Cascading Style Sheets'); $replacement_array[] = array( '-wp-' , 'WordPress'); $replacement_array[] = array( '-wpp-' , 'WordPress plugin'); $replacement_array[] = array( '-wpt-' , 'WordPress theme'); //set the abbreviation repacements $replacement_array[] = array( '~css~' , '<abbr title="Cascading Style Sheets">CSS</abbr>'); $replacement_array[] = array( '~html~' , '<abbr title="Hypertext Markup Language">HTML</abbr>'); //set a variable to keep track of replacements $replaced = 0; foreach( $replacement_array as $replacement ){ //access the post_content and switch the terms $post->post_content = str_replace( $replacement[0] , $replacement[1] , $post->post_content , $i ); //add the number of replacements carried out to the total $replaced += $i; } //trigger an update but only do it if there have been replacements made //wp_update_post will result in this action being triggered again //if we don't check for replacements we will infinitly loop if ( $replaced > 0) { wp_update_post($post); } } ?>
Comparing it to yesterday’s plugin there are some noticeable differences in the first actual line of code. The first is that we are now dealing with an action, so we use the add_action command, instead of add_filter. The second is that there is an extra variable. This isn’t usually required. Most actions pass either no variables, or one variable. Most filters pass one variable. This particular action can pass either one or two variables. We want the second variable and so we need to tell the action to send us them both. That is what the last variable (the number 2) does.
If you miss this, and it is very easy, and common, to do, then you will get the post_id only. You can use the post_id to get the post object by using the command below, but it is easier to just get it passed as part of the function call.
$post = get_post($post_id);
The plugin is really just a simple string replacement that replaces strings such as -css- with the full text: Cascading Style Sheets, or ~css~ with css (note some browsers, IE *cough* don’t display this so don’t worry if you can’t see anything different).
An essential component is that the plugin counts the number of replacements. If some replacements have been made then the plugin will send the amended post object to the WordPress function wp_update_post($post); If no replacements have been made it will not send it. This is very important.
If you recall my explanation of when this action is fired, it is fired whenever post information is sent to the database. That means when we call the update function, sending the post information to the database, the action is called again. If we called it even when the were no replacements we would create an infinite loop which would end badly for all concerned. So, if there are replacements to made the plugin does run twice. But the second time it doesn’t really do very much.
There are ways to prevent it from running at all the second time but for the sake of simplicity I decided to just let it run twice. After all, it isn’t doing any harm.
Unlike yesterday’s plugin this one isn’t running on the blog. You wouldn’t notice the outcome of it, except that it would remove all the conditions ( -css- ) from the plugin code and the description.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Quick N’ Dirty Links
Wednesday
Jan 23, 2008

As this is the first of the Quick N Dirty plugin posts I’m going to explain the basic principles of WordPress plugins before getting to the plugin itself.
So what is a plugin?
At its most basic a WordPress plugin is just a PHP function that is called by WordPress during a specified process. As the plugin writer, you tell WordPress when you want your function to be called by adding your function to a list attached to one of a series of hooks. When WordPress gets to the point in the process that the hook applies to it will run all the functions in that list.
There are two types of hook: actions and filters.
Actions call the functions in the list without passing any data and without expecting any back. Often these are used to add content to the page in some way such as adding a copyright notice in the footer.
Filters are more involved. Filters pass data to the function and require that data, or an amended version, to be sent back. Filters are usually part of a data handling process such as outputing the content of a post to the screen.
For the first quick n’ dirty plugin I am going to use a filter: the_content.
This filter runs as part of the, the_content, template tag. When the tag is used in the template WordPress retrieves the content of the post, passes it through the filters that have hooked into the process, and then outputs it to screen. This means we can add anything we want, or amend anything we want, to the content of each post without altering the information in the database.
The fully commented plugin is included below. The plugin takes the content, retrieves all the links, checks ( using get_bloginfo ) it to see if the link points to my blog, or not, and then adds the links to the end of the post.
<?php /* Plugin Name: Quick N Dirty End of Post Links Plugin URI: http://www.wp-fun.co.uk/2008/01/23/quick-n-dirty-links/ Description: Captures all the links within a post and lists them all at the end of the content. Author: Andrew Rickmann Version: 1 Author URI: http://www.wp-fun.co.uk */ //This is the line that adds your filter into the list. // 'the_content' is the name of the filter // 'qnd_end_of_post_links' is the name of the function, below // 1 is the priority, 1 is called first, 10 last. add_filter('the_content', 'qnd_end_of_post_links' , 1 ); //WordPress will call this function //$content is the full content of the post function qnd_end_of_post_links( $content ){ //a very basic regular expression to get the links $regexlink = '/<a href="[^<]*<\/a>/i'; //apply the regular exporess, the links that match are saved in $matches preg_match_all( $regexlink , $content , $matches ); //create a string to contain the internal and external links $internal = ''; $external = ''; //loop through all the matching links foreach( $matches[0] as $match ) { //check if the link is pointing at our blog url, if so add to the internal string if ( strpos( $match , get_bloginfo('wpurl') ) !== false ) { $internal .= ' - ' . $match; } else { $external .= ' - ' . $match; } } //only add the header to each list if there are links in the list if ( strlen($internal) != 0 ) { $internal = '<h3>Links to my blog</h3>' . $internal; } if ( strlen($external) != 0 ) { $external = '<h3>Links to other blogs</h3>' . $external; } // !!important, filters must return the value or the post will be empty return $content . $internal . $external; } ?>
It is absolutely essential that the function you create has a unique name. If it is the same as any other function in WordPress then it will trigger an error. Plugin authors will always wrap their functions in classes to avoid this; however, for very simple plugins on your own blog, this isn’t really necessary.
This plugin is running on this blog right now. The next two headers and lists are the result of the plugin.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
It could be quite important for theme developers, but I’m really not very happy about the IE8 standards compliance switch.
I don’t see how making developers opt in to standards can be a good thing, or even what the actual point would be.

